mirror of
https://github.com/aclist/dztui.git
synced 2024-12-30 14:12:04 +01:00
Merge pull request #177 from aclist/release/5.6.0-beta.18
feat: open workshop subscriptions
This commit is contained in:
commit
717070ec40
4 changed files with 108 additions and 8 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,5 +1,15 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [5.6.0-beta.18] 2024-12-14
|
||||||
|
### Added
|
||||||
|
- Open Steam workshop subscriptions dialog
|
||||||
|
- Additional logging
|
||||||
|
### Fixed
|
||||||
|
- Empty dialog popups if user manually deletes local mods while application is running
|
||||||
|
- Abort DayZ path discovery if VDF if Steam files are not synched
|
||||||
|
### Changed
|
||||||
|
- Admonish user to restart Steam in error dialog if DayZ path could not be found
|
||||||
|
|
||||||
## [5.6.0-beta.17] 2024-12-14
|
## [5.6.0-beta.17] 2024-12-14
|
||||||
### Added
|
### Added
|
||||||
- Additional logging
|
- Additional logging
|
||||||
|
|
8
dzgui.sh
8
dzgui.sh
|
@ -578,10 +578,10 @@ fetch_helpers_by_sum(){
|
||||||
[[ -f "$config_file" ]] && source "$config_file"
|
[[ -f "$config_file" ]] && source "$config_file"
|
||||||
declare -A sums
|
declare -A sums
|
||||||
sums=(
|
sums=(
|
||||||
["ui.py"]="be3da1e542d14105f4358dd38901e25a"
|
["ui.py"]="99544ccef6060125509c4b689a808a15"
|
||||||
["query_v2.py"]="55d339ba02512ac69de288eb3be41067"
|
["query_v2.py"]="55d339ba02512ac69de288eb3be41067"
|
||||||
["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397"
|
["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397"
|
||||||
["funcs"]="37897aa36bc2fb6286cee02c8bb07258"
|
["funcs"]="98261fdba4323f77c6dd610c1efc4d11"
|
||||||
["lan"]="c62e84ddd1457b71a85ad21da662b9af"
|
["lan"]="c62e84ddd1457b71a85ad21da662b9af"
|
||||||
)
|
)
|
||||||
local author="aclist"
|
local author="aclist"
|
||||||
|
@ -747,7 +747,7 @@ find_library_folder(){
|
||||||
local search_path="$1"
|
local search_path="$1"
|
||||||
steam_path="$(python3 "$helpers_path/vdf2json.py" -i "$1/steamapps/libraryfolders.vdf" \
|
steam_path="$(python3 "$helpers_path/vdf2json.py" -i "$1/steamapps/libraryfolders.vdf" \
|
||||||
| jq -r '.libraryfolders[]|select(.apps|has("221100")).path')"
|
| jq -r '.libraryfolders[]|select(.apps|has("221100")).path')"
|
||||||
if [[ ! $? -eq 0 ]]; then
|
if [[ ! $? -eq 0 ]] || [[ -z $steam_path ]]; then
|
||||||
logger WARN "Failed to parse Steam path using '$search_path'"
|
logger WARN "Failed to parse Steam path using '$search_path'"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
@ -800,7 +800,7 @@ create_config(){
|
||||||
find_library_folder "$default_steam_path"
|
find_library_folder "$default_steam_path"
|
||||||
if [[ -z $steam_path ]]; then
|
if [[ -z $steam_path ]]; then
|
||||||
logger raise_error "Steam path was empty"
|
logger raise_error "Steam path was empty"
|
||||||
zenity --question --text="DayZ not found or not installed at the Steam library given." --ok-label="Choose path manually" --cancel-label="Exit"
|
zenity --question --text="DayZ not found or not installed at the Steam library given. NOTE: if you recently installed DayZ or moved its location, you MUST restart Steam first for these changes to synch." --ok-label="Choose path manually" --cancel-label="Exit"
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
logger INFO "User selected file picker"
|
logger INFO "User selected file picker"
|
||||||
file_picker
|
file_picker
|
||||||
|
|
|
@ -104,6 +104,7 @@ declare -A funcs=(
|
||||||
["Connect by IP"]="validate_and_connect"
|
["Connect by IP"]="validate_and_connect"
|
||||||
["Connect by ID"]="validate_and_connect"
|
["Connect by ID"]="validate_and_connect"
|
||||||
["Connect from table"]="connect_from_table"
|
["Connect from table"]="connect_from_table"
|
||||||
|
["find_id"]="find_id"
|
||||||
["toggle"]="toggle"
|
["toggle"]="toggle"
|
||||||
["Open link"]="open_link"
|
["Open link"]="open_link"
|
||||||
["filter"]="dump_servers"
|
["filter"]="dump_servers"
|
||||||
|
@ -121,6 +122,7 @@ declare -A funcs=(
|
||||||
["is_in_favs"]="is_in_favs"
|
["is_in_favs"]="is_in_favs"
|
||||||
["show_log"]="show_log"
|
["show_log"]="show_log"
|
||||||
["Output system info to log file"]="generate_log"
|
["Output system info to log file"]="generate_log"
|
||||||
|
["open_user_workshop"]="open_user_workshop"
|
||||||
["open_workshop_page"]="open_workshop_page"
|
["open_workshop_page"]="open_workshop_page"
|
||||||
["Add to my servers"]="update_favs_from_table"
|
["Add to my servers"]="update_favs_from_table"
|
||||||
["Remove from my servers"]="update_favs_from_table"
|
["Remove from my servers"]="update_favs_from_table"
|
||||||
|
@ -332,18 +334,32 @@ is_in_favs(){
|
||||||
done
|
done
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
find_id(){
|
||||||
|
local file="$default_steam_path/config/loginusers.vdf"
|
||||||
|
[[ ! -f $file ]] && return 1
|
||||||
|
local res=$(python3 $HOME/.local/share/dzgui/helpers/vdf2json.py \
|
||||||
|
-i "$file" | jq -r '.users
|
||||||
|
|to_entries[]
|
||||||
|
|select(.value.MostRecent=="1")
|
||||||
|
|.key'
|
||||||
|
)
|
||||||
|
[[ -z $res ]] && return 1
|
||||||
|
printf "%s" "$res"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
list_mods(){
|
list_mods(){
|
||||||
local symlink
|
local symlink
|
||||||
local sep
|
local sep
|
||||||
local name
|
local name
|
||||||
local base_dir
|
local base_dir
|
||||||
local size
|
local size
|
||||||
|
local mods
|
||||||
if [[ -z $(installed_mods) ]] || [[ -z $(find $workshop_dir -maxdepth 2 -name "*.cpp" | grep .cpp) ]]; then
|
if [[ -z $(installed_mods) ]] || [[ -z $(find $workshop_dir -maxdepth 2 -name "*.cpp" | grep .cpp) ]]; then
|
||||||
printf "No mods currently installed or incorrect path set."
|
printf "No mods currently installed or incorrect path set."
|
||||||
logger WARN "Found no locally installed mods"
|
logger WARN "Found no locally installed mods"
|
||||||
return 1
|
return 1
|
||||||
else
|
else
|
||||||
for dir in $(find $game_dir/* -maxdepth 1 -type l); do
|
mods=$(for dir in $(find $game_dir/* -maxdepth 1 -type l); do
|
||||||
symlink=$(basename $dir)
|
symlink=$(basename $dir)
|
||||||
sep="␞"
|
sep="␞"
|
||||||
name=$(awk -F\" '/name/ {print $2}' "${dir}/meta.cpp")
|
name=$(awk -F\" '/name/ {print $2}' "${dir}/meta.cpp")
|
||||||
|
@ -351,7 +367,14 @@ list_mods(){
|
||||||
size=$(du -s "$(readlink -f "$game_dir/$symlink")" | awk '{print $1}')
|
size=$(du -s "$(readlink -f "$game_dir/$symlink")" | awk '{print $1}')
|
||||||
size=$(python3 -c "n=($size/1024) +.005; print(round(n,4))")
|
size=$(python3 -c "n=($size/1024) +.005; print(round(n,4))")
|
||||||
LC_NUMERIC=C printf "%s$sep%s$sep%s$sep%3.3f\n" "$name" "$symlink" "$base_dir" "$size"
|
LC_NUMERIC=C printf "%s$sep%s$sep%s$sep%3.3f\n" "$name" "$symlink" "$base_dir" "$size"
|
||||||
done | sort -k1
|
done | sort -k1)
|
||||||
|
# user may have manually pruned mods out-of-band
|
||||||
|
# handle directory detritus but no actual mods
|
||||||
|
if [[ -z $mods ]]; then
|
||||||
|
printf "No mods currently installed or incorrect path set."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "$mods"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
installed_mods(){
|
installed_mods(){
|
||||||
|
@ -1051,6 +1074,12 @@ update_config_val(){
|
||||||
show_log(){
|
show_log(){
|
||||||
< "$debug_log" sed 's/Keyword␞/Keyword/'
|
< "$debug_log" sed 's/Keyword␞/Keyword/'
|
||||||
}
|
}
|
||||||
|
open_user_workshop(){
|
||||||
|
shift
|
||||||
|
local id="$1"
|
||||||
|
url="https://steamcommunity.com/profiles/$id/myworkshopfiles/?appid=$aid&browsefilter=mysubscriptions"
|
||||||
|
$steam_cmd steam://openurl/$url &
|
||||||
|
}
|
||||||
open_workshop_page(){
|
open_workshop_page(){
|
||||||
shift
|
shift
|
||||||
local id="$1"
|
local id="$1"
|
||||||
|
@ -1173,7 +1202,7 @@ legacy_symlinks(){
|
||||||
logger INFO "Removing legacy symlinks"
|
logger INFO "Removing legacy symlinks"
|
||||||
for d in "$game_dir"/*; do
|
for d in "$game_dir"/*; do
|
||||||
if [[ $d =~ @[0-9]+-.+ ]]; then
|
if [[ $d =~ @[0-9]+-.+ ]]; then
|
||||||
logger INFO "Unlinking $d"
|
logger INFO "Unlinking '$d'"
|
||||||
unlink "$d"
|
unlink "$d"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
@ -1183,11 +1212,14 @@ legacy_symlinks(){
|
||||||
logger INFO "Removing legacy encoding format"
|
logger INFO "Removing legacy encoding format"
|
||||||
for d in "${mod_dirs[@]}"; do
|
for d in "${mod_dirs[@]}"; do
|
||||||
# suppress errors if mods are downloading at boot
|
# suppress errors if mods are downloading at boot
|
||||||
|
logger INFO "Testing directory '$d'"
|
||||||
[[ ! -f "$d/meta.cpp" ]] && continue
|
[[ ! -f "$d/meta.cpp" ]] && continue
|
||||||
local id=$(awk -F"= " '/publishedid/ {print $2}' "$d"/meta.cpp | awk -F\; '{print $1}')
|
local id=$(awk -F"= " '/publishedid/ {print $2}' "$d"/meta.cpp | awk -F\; '{print $1}')
|
||||||
|
logger INFO "Given id is '$id'"
|
||||||
local encoded_id=$(echo "$id" | awk '{printf("%c",$1)}' | base64 | sed 's/\//_/g; s/=//g; s/+/]/g')
|
local encoded_id=$(echo "$id" | awk '{printf("%c",$1)}' | base64 | sed 's/\//_/g; s/=//g; s/+/]/g')
|
||||||
|
logger INFO "Resolved id is '$encoded_id'"
|
||||||
if [[ -h "$game_dir/@$encoded_id" ]]; then
|
if [[ -h "$game_dir/@$encoded_id" ]]; then
|
||||||
logger INFO "Unlinking $game_dir/@$encoded_id"
|
logger INFO "Unlinking '$game_dir/@$encoded_id'"
|
||||||
unlink "$game_dir/@$encoded_id"
|
unlink "$game_dir/@$encoded_id"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
|
@ -215,6 +215,7 @@ class RowType(EnumWithAttrs):
|
||||||
"label": "Toggle mod install mode",
|
"label": "Toggle mod install mode",
|
||||||
"tooltip": "Switch between manual and auto mod installation",
|
"tooltip": "Switch between manual and auto mod installation",
|
||||||
"default": "manual",
|
"default": "manual",
|
||||||
|
"link_label": "Open Steam Workshop",
|
||||||
"alt": "auto",
|
"alt": "auto",
|
||||||
"val": "auto_install"
|
"val": "auto_install"
|
||||||
}
|
}
|
||||||
|
@ -756,6 +757,29 @@ def process_tree_option(input, treeview):
|
||||||
case RowType.TGL_BRANCH:
|
case RowType.TGL_BRANCH:
|
||||||
wait_msg = "Updating DZGUI branch"
|
wait_msg = "Updating DZGUI branch"
|
||||||
call_on_thread(False, "toggle", wait_msg, cmd_string)
|
call_on_thread(False, "toggle", wait_msg, cmd_string)
|
||||||
|
case RowType.TGL_INSTALL:
|
||||||
|
if query_config(None, "auto_install")[0] == "1":
|
||||||
|
proc = call_out(transient_parent, "toggle", cmd_string)
|
||||||
|
grid.update_right_statusbar()
|
||||||
|
tooltip = format_metadata(command.dict["label"])
|
||||||
|
transient_parent.grid.update_statusbar(tooltip)
|
||||||
|
return
|
||||||
|
# manual -> auto mode
|
||||||
|
proc = call_out(transient_parent, "find_id", "")
|
||||||
|
if proc.returncode == 1:
|
||||||
|
link=None
|
||||||
|
uid=None
|
||||||
|
else:
|
||||||
|
link=command.dict["link_label"]
|
||||||
|
uid=proc.stdout
|
||||||
|
manual_sub_msg = """\
|
||||||
|
When switching from MANUAL to AUTO mod install mode,
|
||||||
|
DZGUI will manage mod installation and deletion for you.
|
||||||
|
To prevent conflicts with Steam Workshop subscriptions and old mods from being downloaded
|
||||||
|
when Steam updates, you should unsubscribe from any existing Workshop mods you manually subscribed to.
|
||||||
|
Open your Profile > Workshop Items and select 'Unsubscribe from all'
|
||||||
|
on the right-hand side, then click OK below to enable AUTO mod install mode."""
|
||||||
|
LinkDialog(transient_parent, textwrap.dedent(manual_sub_msg), Popup.NOTIFY, link, command, uid)
|
||||||
case _:
|
case _:
|
||||||
proc = call_out(transient_parent, "toggle", cmd_string)
|
proc = call_out(transient_parent, "toggle", cmd_string)
|
||||||
grid.update_right_statusbar()
|
grid.update_right_statusbar()
|
||||||
|
@ -2205,6 +2229,40 @@ class ModDialog(GenericDialog):
|
||||||
subprocess.Popen(['/usr/bin/env', 'bash', funcs, "open_workshop_page", mod_id])
|
subprocess.Popen(['/usr/bin/env', 'bash', funcs, "open_workshop_page", mod_id])
|
||||||
|
|
||||||
|
|
||||||
|
class LinkDialog(GenericDialog):
|
||||||
|
def __init__(self, parent, text, mode, link, command, uid=None):
|
||||||
|
super().__init__(parent, text, mode)
|
||||||
|
|
||||||
|
self.dialog = GenericDialog(parent, text, mode)
|
||||||
|
self.dialogBox = self.dialog.get_content_area()
|
||||||
|
self.dialog.set_default_response(Gtk.ResponseType.OK)
|
||||||
|
self.dialog.set_size_request(500, 0)
|
||||||
|
|
||||||
|
if link is not None:
|
||||||
|
button = Gtk.Button(label=link)
|
||||||
|
button.set_margin_start(60)
|
||||||
|
button.set_margin_end(60)
|
||||||
|
button.connect("clicked", self._on_button_clicked, uid)
|
||||||
|
self.dialogBox.pack_end(button, False, False, 0)
|
||||||
|
|
||||||
|
self.dialog.show_all()
|
||||||
|
self.dialog.connect("response", self._on_dialog_response, parent, command)
|
||||||
|
|
||||||
|
def _on_button_clicked(self, button, uid):
|
||||||
|
subprocess.Popen(['/usr/bin/env', 'bash', funcs, "open_user_workshop", uid])
|
||||||
|
|
||||||
|
def _on_dialog_response(self, dialog, resp, parent, command):
|
||||||
|
match resp:
|
||||||
|
case Gtk.ResponseType.DELETE_EVENT:
|
||||||
|
return
|
||||||
|
case Gtk.ResponseType.OK:
|
||||||
|
self.dialog.destroy()
|
||||||
|
proc = call_out(parent, "toggle", command.dict["label"])
|
||||||
|
parent.grid.update_right_statusbar()
|
||||||
|
tooltip = format_metadata(command.dict["label"])
|
||||||
|
parent.grid.update_statusbar(tooltip)
|
||||||
|
|
||||||
|
|
||||||
class EntryDialog(GenericDialog):
|
class EntryDialog(GenericDialog):
|
||||||
def __init__(self, parent, text, mode, link):
|
def __init__(self, parent, text, mode, link):
|
||||||
super().__init__(parent, text, mode)
|
super().__init__(parent, text, mode)
|
||||||
|
|
Loading…
Reference in a new issue