mirror of
https://github.com/aclist/dztui.git
synced 2026-11-05 09:34:46 +01:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f46cea0ab8 |
No files matched your search
@@ -5,10 +5,6 @@ labels: ["bug"]
|
||||
assignees:
|
||||
- aclist
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### WARNING: When posting log/config data, redact any sensitive information like API keys.
|
||||
- type: checkboxes
|
||||
id: kb
|
||||
attributes:
|
||||
|
||||
@@ -5,10 +5,6 @@ labels: ["troubleshooting"]
|
||||
assignees:
|
||||
- aclist
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### WARNING: When posting log/config data, redact any sensitive information like API keys.
|
||||
- type: dropdown
|
||||
id: device
|
||||
attributes:
|
||||
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
mirror-to-codeberg:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: pixta-dev/repository-mirroring-action@v1
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
tags
|
||||
__pycache__
|
||||
pre-commit
|
||||
tests/
|
||||
+11
-116
@@ -1,125 +1,20 @@
|
||||
# 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
|
||||
## Fixed
|
||||
- Update A2S module checksums to support servers with missing description field
|
||||
## Changed
|
||||
- Bump version to reflect hotfixes on stable branch
|
||||
|
||||
## [6.0.2-beta.5] 2026-04-12
|
||||
## Fixed
|
||||
- Use conditional logic when testing GLibUnix namespaces
|
||||
|
||||
## [6.0.2-beta.4] 2026-04-10
|
||||
## Fixed
|
||||
- Use GLibUnix namespace when setting up SIGINT handling
|
||||
|
||||
## [6.0.2-beta.3] 2026-01-26
|
||||
## Fixed
|
||||
- Raise error correctly from module
|
||||
|
||||
## [6.0.2-beta.2] 2026-01-18
|
||||
## Fixed
|
||||
- Helpers not being downloaded (uncommented boilerplate)
|
||||
|
||||
## [6.0.2-beta.1] 2026-01-18
|
||||
## Fixed
|
||||
- Do not spawn dialogs from inside of thread when fetching prereqs
|
||||
## Changed
|
||||
- Optimize time complexity of startup checks
|
||||
- Optimize coordinate calculation by using local records first
|
||||
- Rename some internal functions
|
||||
- Wrap entire startup process in dialog
|
||||
|
||||
## [6.0.1-beta.1] 2026-01-16
|
||||
## Fixed
|
||||
- Explicitly use Python 3.13 when calling subprocesses
|
||||
|
||||
## [6.0.0-beta.20] 2026-01-14
|
||||
## Fixed
|
||||
- Write cache file after wiping
|
||||
|
||||
## [6.0.0-beta.19] 2026-01-14
|
||||
## Fixed
|
||||
- Steam Deck compatible script path expansion
|
||||
|
||||
## [6.0.0-beta.18] 2026-01-14
|
||||
## Fixed
|
||||
- Update UI checksums
|
||||
|
||||
## [6.0.0-beta.17] 2026-01-14
|
||||
## [6.0.0-beta.8] XXXX-XX-XX
|
||||
## Added
|
||||
- More descriptive help dialogs when initial dependencies are missing
|
||||
|
||||
## [6.0.0-beta.16] 2026-01-04
|
||||
## Fixed
|
||||
- Regression introduced in previous hotfix
|
||||
|
||||
## [6.0.0-beta.15] 2025-12-27
|
||||
## Fixed
|
||||
- Path discovery during first-time setup when parsing filepaths with whitespaces
|
||||
- First-time setup dialog continuously triggering when DayZ install path had whitespaces in it
|
||||
|
||||
## [6.0.0-beta.14] 2025-12-09
|
||||
## Fixed
|
||||
- Dialogs with newlines breaking output in log table
|
||||
|
||||
## [6.0.0-beta.13] 2025-11-29
|
||||
## Fixed
|
||||
- Server filter panel not being hidden when entering other page contexts
|
||||
- Path to remote changelog being constructed incorrectly
|
||||
|
||||
## [6.0.0-beta.12] 2025-11-14
|
||||
## Changed
|
||||
- Require Python 3.13
|
||||
## Fixed
|
||||
- Normalize beta version
|
||||
|
||||
## [6.0.0-beta.11] 2025-11-13
|
||||
## Added
|
||||
- Support sandboxed flatpak
|
||||
|
||||
## Changed
|
||||
- Preferred client from radio toggle to combobox
|
||||
|
||||
## Fixed
|
||||
- Config file erroneously getting updated when populating settings menu
|
||||
|
||||
## [6.0.0-beta.10] 2025-11-10
|
||||
## Fixed
|
||||
- Python 3.14 error in finally block
|
||||
- Require Python version between 3.11 and 3.12
|
||||
|
||||
## [6.0.0-beta.9] 2025-11-05
|
||||
## Fixed
|
||||
- UI not being constructed correctly if CHANGELOG.md was missing
|
||||
|
||||
## [6.0.0-beta.8] 2025-11-04
|
||||
## Added
|
||||
- Internal flag to allow distribution packaged releases to disable in-app updates
|
||||
- Pre-boot check to test whether script was invoked directly
|
||||
- Flag to disable branch toggle for distro-packaged releases
|
||||
- Test whether script was sourced inline
|
||||
- Commandline usage help text
|
||||
|
||||
## Fixed
|
||||
- ESC key destroying wait dialogs while a thread is pending
|
||||
- Tooltip signals being erroneously drawn on main menu
|
||||
- Leaky variable name in dialog titles
|
||||
- ESC key destroying wait dialogs while thread is pending
|
||||
- Tooltip signals being processed on main menu
|
||||
- Leaky variable name in dialog title
|
||||
- Prevent extraneous signals from propagating when column width is adjusted
|
||||
- Script failing to start when remote endpoints are unavailable (GaryBlackbourne)
|
||||
- Script failing to start when remote endpoints are unavailable
|
||||
|
||||
## Changed
|
||||
- Optimize time complexity of pre-boot checks (GaryBlackbourne)
|
||||
- Moved location of notes file
|
||||
- Rewrote distance calculation module (GaryBlackbourne)
|
||||
- Optimize time cost of setup checks
|
||||
|
||||
## [6.0.0-beta.7] 2025-09-20
|
||||
## Added
|
||||
@@ -616,7 +511,7 @@ As part of this change, version 4.0.0 introduces the ability to connect to or ad
|
||||
|
||||
If you encounter any problems with this new release or with the migration of configs, please do not hesitate to submit a bug report.
|
||||
|
||||
Attention Fedora 38 users: problems with upstream GNOME packages causing crashes have been reported to GNOME development and a fix has been issued. You have the choice of compiling the zenity package
|
||||
Attention Fedora 38 users: problems with upstream GNOME packages causing crashes have been reported to GNOME development and a fix has been issued. You have the choice of compiling the zenity package
|
||||
from source or waiting until the latest version is merged into Fedora's package manager.
|
||||
|
||||
### Added
|
||||
@@ -641,7 +536,7 @@ from source or waiting until the latest version is merged into Fedora's package
|
||||
- Store complete IP:Port instead of server IDs
|
||||
- Make Battlemetrics API key optional: this is only used for the 'Connect by ID' and 'Add server by ID' methods and is not required. If you prefer, you can simply connect/add by IP.
|
||||
- Prevent the application from launching in Game Mode on Steam Deck: Steam Deck's kiosk mode has problems sending keyboard input to third party applications. To prevent unintended usage, DZGUI now warns the user to launch the app in Desktop Mode if they attempt to use it from Game Mode. Adding DZGUI as a Non-Steam Game does work on desktop PCs, but is not recommended due to the way Steam handles subshells. For best results, launch DZGUI directly via the script/applications menu (PC) or via the desktop icon (Steam Deck).
|
||||
- Omit null servers from list: servers that time out or send an empty response are now omitted entirely from the My Servers list, as they will not return meaningful metadata unless they are online.
|
||||
- Omit null servers from list: servers that time out or send an empty response are now omitted entirely from the My Servers list, as they will not return meaningful metadata unless they are online.
|
||||
The My Servers list thus shows online and accessible servers
|
||||
|
||||
## [3.3.0] 2023-05-16
|
||||
@@ -660,7 +555,7 @@ from source or waiting until the latest version is merged into Fedora's package
|
||||
- First-time setup: sudo escalation when checking system map count for the first time
|
||||
|
||||
### Fixed
|
||||
- Steam Deck: non-ASCII delimiter causing setup menu to despawn on some devices
|
||||
- Steam Deck: non-ASCII delimiter causing setup menu to despawn on some devices
|
||||
- Don't add items in My Servers multiple times to array when the list of favorites is paginated
|
||||
- Trigger progress dialogs sooner and in sequence to reduce appearance of visual lag
|
||||
- First-time setup: break out of dialogs correctly when user backs out
|
||||
|
||||
+6
-8
@@ -8,7 +8,7 @@ If you are a developer, you can skip to the end.
|
||||
# Requesting help
|
||||
|
||||
If you encounter a problem with DZGUI, you can submit tickets on the GitHub
|
||||
[issue tracker](https://github.com/aclist/dztui/issues) under the
|
||||
(issue tracker)[https://github.com/aclist/dzgui-devel/issues] under the
|
||||
`troubleshooting` tag.
|
||||
|
||||
# How can I help the project?
|
||||
@@ -24,7 +24,7 @@ accordingly.
|
||||
|
||||
## Submitting a ticket
|
||||
|
||||
Navigate to the GitHub [issue tracker](https://github.com/aclist/dztui/issues).
|
||||
Navigate to the GitHub (issue tracker)[https://github.com/aclist/dzgui-devel/issues].
|
||||
From there, follow the onscreen prompts. You will be asked questions such as:
|
||||
|
||||
- What version are you using?
|
||||
@@ -50,10 +50,8 @@ If you would like to take ownership or assist with an issue on the issue tracker
|
||||
contribute a new change, please follow the guidelines below.
|
||||
|
||||
Fork this repository and check out the code up to `prerelease/<latest-version>`.
|
||||
If there is no pending prerelease PR, you can base your changes off of
|
||||
the `testing` branch. You may later be asked to retarget your PR to the prerelease
|
||||
branch once a new one is made. This is because out-of-band PRs are consolidated into
|
||||
the next release before merging.
|
||||
All new features and fixes will be merged to this branch, so open your branch
|
||||
from here.
|
||||
|
||||
The following naming conventions apply for PRs:
|
||||
- fix/<your-fix> - patch/hotfix branches
|
||||
@@ -63,9 +61,9 @@ The following naming conventions apply for PRs:
|
||||
|
||||
Implement your changes and test them locally. If they work you may
|
||||
open a merge request, and then we review your changes. If everything is OK, it
|
||||
will be merged to `prerelease/<latest-version>`, then `testing`, and after a live
|
||||
will be merged to `prerelease/<latest-version>`, then `testing` and after a live
|
||||
testing phase, to `stable` as well.
|
||||
|
||||
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.
|
||||
@@ -11,15 +11,6 @@ This overcomes certain limitations in the Linux client and helps prepare the gam
|
||||
- Concatenate launch options to pass to Steam
|
||||
- Connect to mod-enabled LAN servers
|
||||
|
||||
## Design philosophy
|
||||
|
||||
DZGUI follows a specific set of guidelines, enumerated below:
|
||||
|
||||
- Provide a free and open-source tool under GPL
|
||||
- Do not use undocumented, third-party servers to aggregate data; no central "DZGUI" server
|
||||
- All connections go to Steam and DayZ servers directly; the tool should function in perpetuity without intermediary endpoints
|
||||
- Target Linux desktop and Steam deck specifically; not a cross-platform tool
|
||||
|
||||
## Setup and usage
|
||||
|
||||
Refer to the documentation for installation and setup instructions:
|
||||
@@ -27,6 +18,7 @@ Refer to the documentation for installation and setup instructions:
|
||||
- [GitHub](https://aclist.github.io/dzgui/index.html)
|
||||
- [Mirror (Codeberg)](https://aclist.codeberg.page)
|
||||
|
||||
|
||||

|
||||
|
||||
## Attribution
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o pipefail
|
||||
|
||||
src_path="$(readlink -e "$0")"
|
||||
version=6.0.6-beta.1
|
||||
version=6.0.0.beta-8
|
||||
|
||||
#CONSTANTS
|
||||
aid=221100
|
||||
@@ -40,7 +39,6 @@ cols_file="$state_path/$prefix.cols.json"
|
||||
|
||||
#CACHE FILES
|
||||
coords_file="$cache_path/$prefix.coords"
|
||||
src_path_file="$cache_path/$prefix.src"
|
||||
|
||||
#legacy paths
|
||||
hist_file="$config_path/history"
|
||||
@@ -117,7 +115,6 @@ setup_state_files(){
|
||||
done
|
||||
logger INFO "Wiped cache files"
|
||||
fi
|
||||
echo "$src_path" > "$src_path_file"
|
||||
}
|
||||
print_config_vals(){
|
||||
local keys=(
|
||||
@@ -139,10 +136,10 @@ print_config_vals(){
|
||||
|
||||
}
|
||||
test_gobject(){
|
||||
python3.13 -c "import gi"
|
||||
python3 -c "import gi"
|
||||
if [[ ! $? -eq 0 ]]; then
|
||||
logger CRITICAL "Missing PyGObject"
|
||||
quit_with_help_dialog "Requires PyGObject (python-gobject)"
|
||||
fdialog "Requires PyGObject (python-gobject)"
|
||||
exit 1
|
||||
fi
|
||||
logger INFO "Found PyGObject in Python env"
|
||||
@@ -221,14 +218,16 @@ default_steam_path="$default_steam_path"
|
||||
|
||||
#Preferred Steam launch command (for Flatpak support)
|
||||
preferred_client="$preferred_client"
|
||||
|
||||
#DZGUI source path
|
||||
src_path="$src_path"
|
||||
END
|
||||
}
|
||||
depcheck(){
|
||||
for dep in "${!deps[@]}"; do
|
||||
if ! command -v "$dep" &> /dev/null; then
|
||||
local msg="Requires $dep >= ${deps[$dep]}"
|
||||
echo "$msg"
|
||||
exit 1
|
||||
raise_error_and_quit "$msg"
|
||||
fi
|
||||
done
|
||||
local jqmsg="jq must be compiled with support for oniguruma"
|
||||
@@ -237,31 +236,14 @@ depcheck(){
|
||||
[[ $? -ne 0 ]] && raise_error_and_quit "$jqmsg"
|
||||
logger INFO "Initial dependencies satisfied"
|
||||
}
|
||||
open_url(){
|
||||
url="$1"
|
||||
if [[ -n "$BROWSER" ]]; then
|
||||
logger INFO "Opening '$url' in '$BROWSER'"
|
||||
"$BROWSER" "$url"
|
||||
else
|
||||
logger INFO "Opening '$url' with xdg-open"
|
||||
xdg-open "$url"
|
||||
fi
|
||||
}
|
||||
quit_with_help_dialog(){
|
||||
local sel
|
||||
msg="$1"
|
||||
help_button="Open help page"
|
||||
url="https://aclist.github.io/dzgui/installation.html"
|
||||
logger CRITICAL "$msg"
|
||||
sel=$(zenity --info --extra-button="$help_button" --text="$msg")
|
||||
[[ $sel == "$help_button" ]] && open_url "$url" &
|
||||
exit 1
|
||||
}
|
||||
check_pyver(){
|
||||
if [[ ! $(python3.13 --version) ]]; then
|
||||
local msg="Requires Python 3.13"
|
||||
quit_with_help_dialog "$msg"
|
||||
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
|
||||
@@ -335,8 +317,6 @@ check_unmerged(){
|
||||
fi
|
||||
}
|
||||
check_version(){
|
||||
echo "# Checking version"
|
||||
[[ -n $reference_branch ]] && return
|
||||
local version_url=$(format_version_url)
|
||||
local upstream=$(curl -Ls "$version_url" | awk -F= '/^version=/ {print $2}')
|
||||
local res=$(get_response_code "$version_url")
|
||||
@@ -386,7 +366,7 @@ prompt_dl(){
|
||||
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
|
||||
}
|
||||
@@ -400,11 +380,10 @@ prompt_dl(){
|
||||
dl_changelog(){
|
||||
local mdbranch
|
||||
local md
|
||||
source "$config_file"
|
||||
[[ $branch == "stable" ]] && mdbranch="dzgui"
|
||||
[[ $branch == "testing" ]] && mdbranch="testing"
|
||||
local changelog="$url_prefix/${mdbranch}/CHANGELOG.md"
|
||||
curl -Ls "$changelog" > "$state_path/CHANGELOG.md"
|
||||
local md="$url_prefix/${mdbranch}/$file"
|
||||
curl -Ls "$md" > "$state_path/CHANGELOG.md"
|
||||
}
|
||||
test_display_mode(){
|
||||
pgrep -a gamescope | grep -q "generate-drm-mode"
|
||||
@@ -415,7 +394,6 @@ test_display_mode(){
|
||||
fi
|
||||
}
|
||||
check_architecture(){
|
||||
echo "# Checking system architecture"
|
||||
local cpu=$(< /proc/cpuinfo awk -F": " '/AMD Custom APU [0-9]{4}$/ {print $2; exit}')
|
||||
read -a APU_MODEL <<< "$cpu"
|
||||
if [[ ${APU_MODEL[3]} != "0932" ]] && [[ ${APU_MODEL[3]} != "0405" ]]; then
|
||||
@@ -432,7 +410,6 @@ check_architecture(){
|
||||
logger INFO "Setting architecture to 'Steam Deck'"
|
||||
}
|
||||
check_map_count(){
|
||||
echo "# Checking map count"
|
||||
[[ $is_steam_deck -gt 0 ]] && return 0
|
||||
local map_count_file="/proc/sys/vm/max_map_count"
|
||||
local min_count=1048576
|
||||
@@ -482,7 +459,6 @@ tdialog(){
|
||||
$steamsafe_zenity --info --text="$1" "${zenity_flags[@]}"
|
||||
}
|
||||
steam_deps(){
|
||||
echo "# Checking Steam"
|
||||
local flatpak
|
||||
local steam
|
||||
[[ $(command -v flatpak) ]] && flatpak=$(flatpak list | grep valvesoftware.Steam)
|
||||
@@ -491,15 +467,33 @@ steam_deps(){
|
||||
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"
|
||||
fi
|
||||
elif [[ -n "$steam" ]]; then
|
||||
preferred_client="steam"
|
||||
else
|
||||
preferred_client="flatpak"
|
||||
fi
|
||||
update_config
|
||||
logger INFO "Preferred client set to '$preferred_client'"
|
||||
}
|
||||
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"
|
||||
}
|
||||
stale_symlinks(){
|
||||
echo "# Cleaning stale symlinks"
|
||||
local game_dir="$steam_path/steamapps/common/DayZ"
|
||||
readarray -t links < <(find "$game_dir" -xtype l)
|
||||
for link in "${links[@]}"; do
|
||||
logger DEBUG "Updating stale symlink '$link'"
|
||||
unlink "$link"
|
||||
for l in $(find "$game_dir" -xtype l); do
|
||||
logger DEBUG "Updating stale symlink '$l'"
|
||||
unlink "$l"
|
||||
done
|
||||
}
|
||||
|
||||
@@ -508,7 +502,7 @@ check_availability() {
|
||||
return 1
|
||||
fi
|
||||
local url=$1
|
||||
local timeout_sec="1"
|
||||
local timeout_sec="3"
|
||||
if [[ $2 ]]; then
|
||||
timeout_sec=$2
|
||||
fi
|
||||
@@ -519,7 +513,6 @@ check_availability() {
|
||||
}
|
||||
|
||||
local_latlon(){
|
||||
echo "# Checking coordinates"
|
||||
if [[ -z $(command -v dig) ]]; then
|
||||
local url_ipecho="https://ipecho.net/plain"
|
||||
if ! check_availability "ipecho.net"; then
|
||||
@@ -531,9 +524,6 @@ local_latlon(){
|
||||
# TODO : implement checking remote
|
||||
local local_ip=$(dig -4 +short myip.opendns.com @resolver1.opendns.com)
|
||||
fi
|
||||
if calc_local_coords "$local_ip"; then
|
||||
return 0
|
||||
fi
|
||||
local url_ip_api="http://ip-api.com/json/$local_ip"
|
||||
if ! check_availability "ip-api.com"; then
|
||||
logger WARN "Failed to get local coordinates, ip-api.com service may be down."
|
||||
@@ -548,7 +538,6 @@ local_latlon(){
|
||||
}
|
||||
|
||||
lock(){
|
||||
echo "# Setting up lock file"
|
||||
[[ ! -f $lock_file ]] && touch $lock_file
|
||||
local pid=$(cat $lock_file)
|
||||
ps -p $pid -o pid= >/dev/null 2>&1
|
||||
@@ -567,12 +556,9 @@ get_hash(){
|
||||
md5sum "$1" | awk '{print $1}'
|
||||
}
|
||||
fetch_a2s(){
|
||||
sum="d26da2fe03df2b95436f823f0496887b"
|
||||
if [[ -d $helpers_path/a2s ]] && [[ $(get_hash "$helpers_path/a2s/info.py") == $sum ]]; then
|
||||
logger INFO "A2S helper is current"
|
||||
return 0
|
||||
fi
|
||||
local sha=b40eb24cdbb06ebd08272f224257fe5a81610e86
|
||||
# this file is currently monolithic
|
||||
[[ -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"
|
||||
@@ -586,13 +572,13 @@ fetch_a2s(){
|
||||
logger INFO "Updated A2S helper to sha '$sha'"
|
||||
}
|
||||
fetch_dzq(){
|
||||
local sum="0d316badbb8d943c5f078e73862cac3e"
|
||||
local sum="0a334e1e144e76e560419d155435c91e"
|
||||
local file="$helpers_path/a2s/dayzquery.py"
|
||||
if [[ -f $file ]] && [[ $(get_hash "$file") == $sum ]]; then
|
||||
logger INFO "DZQ is current"
|
||||
return 0
|
||||
fi
|
||||
local sha="07483b88ed096327ebca752f5e177011b604d7fe"
|
||||
local sha=a22a9f428cbe075d7dda62f78000296955eea92a
|
||||
local author="yepoleb"
|
||||
local repo="dayzquery"
|
||||
local url="https://raw.githubusercontent.com/$author/$repo/$sha/dayzquery.py"
|
||||
@@ -629,12 +615,12 @@ fetch_helpers_by_sum(){
|
||||
[[ -f "$config_file" ]] && source "$config_file"
|
||||
declare -A sums
|
||||
sums=(
|
||||
["funcs"]="1cd26343cd68a5382e3377a9757497fa"
|
||||
["funcs"]="6ae3ead7034dc8e7543472bddee75c63"
|
||||
["query_v2.py"]="55d339ba02512ac69de288eb3be41067"
|
||||
["servers.py"]="ed442c3aecf33f777d59dcf53650d263"
|
||||
["ui.py"]="cf52a3d5883afe02a013d8673df494fa"
|
||||
["ui.py"]="f03879f088ad074f2ce3c92607c30202"
|
||||
["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397"
|
||||
["pefile.py"]="b452974a84bff1d821872fcebf59e380"
|
||||
["pefile.py"]="21531f2c0d9dfa5f110cf6779f9d22c0"
|
||||
)
|
||||
local author="aclist"
|
||||
local repo="dztui"
|
||||
@@ -653,10 +639,6 @@ fetch_helpers_by_sum(){
|
||||
realbranch="dzgui"
|
||||
fi
|
||||
|
||||
if [[ -n $reference_branch ]]; then
|
||||
realbranch="$reference_branch"
|
||||
fi
|
||||
|
||||
for i in "${!sums[@]}"; do
|
||||
file="$i"
|
||||
sum="${sums[$i]}"
|
||||
@@ -694,12 +676,15 @@ fetch_km_helper(){
|
||||
}
|
||||
get_response_code(){
|
||||
local url="$1"
|
||||
curl --connect-timeout 3 -Ls -I -o /dev/null -w "%{http_code}" "$url"
|
||||
curl -Ls -I -o /dev/null -w "%{http_code}" "$url"
|
||||
}
|
||||
raise_error_and_quit(){
|
||||
echo "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
fetch_ip_db(){
|
||||
parse_dl_url(){
|
||||
curl --connect-timeout 3 -Ls "$url" \
|
||||
curl -Ls "$url" \
|
||||
| grep "csv.gz" \
|
||||
| awk -F"['']" '{print $2}'
|
||||
}
|
||||
@@ -715,9 +700,6 @@ fetch_ip_db(){
|
||||
fetch(){
|
||||
logger INFO "Triggering fetch routine"
|
||||
local url="$1"
|
||||
local ip_file="${state_path}/ips.csv"
|
||||
local base_file="${state_path}/${this_month}.csv.gz"
|
||||
local extracted_file="${state_path}/${this_month}.csv"
|
||||
|
||||
curl -Ls "$url" > "$base_file"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
@@ -737,7 +719,7 @@ fetch_ip_db(){
|
||||
logger WARN "Abnormal exit while parsing IPs"
|
||||
return
|
||||
fi
|
||||
rm "${state_path}/${this_month}.csv"
|
||||
rm "${state_path}/${month}.csv"
|
||||
|
||||
readarray -t records < <(cat $ip_file | awk -F, 'NR==1 {print $1} END {print $1}')
|
||||
if [[ ${records[0]} != "0.0.0.0" ]] && [[ ${records[1]} != "224.0.0.0" ]]; then
|
||||
@@ -752,57 +734,55 @@ fetch_ip_db(){
|
||||
rm "$ip_file"
|
||||
fi
|
||||
|
||||
echo "$this_month" > "$month_file"
|
||||
logger INFO "Wrote '$this_month' to stub '$month_file'"
|
||||
echo "$month" > "$month_file"
|
||||
logger INFO "Wrote '$month' to stub '$month_file'"
|
||||
logger INFO "Updated '$ip_file'"
|
||||
}
|
||||
|
||||
check_remote(){
|
||||
local url="$1"
|
||||
local res=$(get_response_code "$url")
|
||||
if [[ $res -ne 200 ]]; then
|
||||
logger WARN "Failed to retrieve remote resource: '$url' ($res)"
|
||||
return
|
||||
fi
|
||||
logger INFO "Resolved remote URL: '$url'"
|
||||
|
||||
# test dl url
|
||||
local dl_url="$(parse_dl_url)"
|
||||
local res=$(get_response_code "$dl_url")
|
||||
if [[ $res -ne 200 ]]; then
|
||||
logger WARN "Remote resource unavailable: '$dl_url' ($res)"
|
||||
return
|
||||
fi
|
||||
logger INFO "Resolved download URL: '$dl_url'"
|
||||
fetch "$dl_url"
|
||||
}
|
||||
|
||||
local url="https://db-ip.com/db/download/ip-to-city-lite"
|
||||
month_file="${state_path}/.month"
|
||||
this_month=$(date +%Y-%m)
|
||||
local month_file="${state_path}/.month"
|
||||
local ip_file="${state_path}/ips.csv"
|
||||
|
||||
# test main url
|
||||
local res=$(get_response_code "$url")
|
||||
if [[ $res -ne 200 ]]; then
|
||||
logger WARN "Failed to retrieve remote resource: '$url' ($res)"
|
||||
return
|
||||
fi
|
||||
logger INFO "Resolved remote URL: '$url'"
|
||||
|
||||
# test dl url
|
||||
local dl_url="$(parse_dl_url)"
|
||||
local res=$(get_response_code "$dl_url")
|
||||
if [[ $res -ne 200 ]]; then
|
||||
logger WARN "Remote resource unavailable: '$dl_url' ($res)"
|
||||
return
|
||||
fi
|
||||
logger INFO "Resolved download URL: '$dl_url'"
|
||||
|
||||
local month=$(parse_dl_url_date "$dl_url")
|
||||
local base_file="${state_path}/${month}.csv.gz"
|
||||
local extracted_file="${state_path}/${month}.csv"
|
||||
|
||||
# no stub file
|
||||
if [[ ! -f $month_file ]]; then
|
||||
logger WARN "No stub file '$month_file' present"
|
||||
check_remote "$url"
|
||||
return
|
||||
fi
|
||||
|
||||
# if stub is same date, abort
|
||||
local last_month=$(< "$month_file")
|
||||
if [[ $last_month == "$this_month" ]]; then
|
||||
logger INFO "Local stub '$last_month' is identical to remote, skipping"
|
||||
fetch "$dl_url"
|
||||
return
|
||||
fi
|
||||
|
||||
# local needs update
|
||||
logger WARN "Local stub '$last_month' does not match '$this_month'"
|
||||
check_remote "$url"
|
||||
return
|
||||
local last_month=$(< "$month_file")
|
||||
if [[ $last_month != "$month" ]]; then
|
||||
logger WARN "Local stub '$last_month' does not match remote stub '$month'"
|
||||
fetch "$dl_url"
|
||||
return
|
||||
fi
|
||||
|
||||
# if stub is same date, abort
|
||||
logger INFO "Local stub '$last_month' is identical to remote, skipping"
|
||||
}
|
||||
fetch_helpers(){
|
||||
echo "# Checking helper files"
|
||||
fetch_a2s
|
||||
fetch_dzq
|
||||
fetch_km_helper
|
||||
@@ -901,26 +881,12 @@ file_picker(){
|
||||
}
|
||||
find_library_folder(){
|
||||
local search_path="$1"
|
||||
readarray -t paths < <(python3.13 "$helpers_path/vdf2json.py" -i "$1/steamapps/libraryfolders.vdf" \
|
||||
| jq -r '.libraryfolders[]|select(.apps|has("221100")).path')
|
||||
if [[ ! $? -eq 0 ]]; then
|
||||
steam_path="$(python3 "$helpers_path/vdf2json.py" -i "$1/steamapps/libraryfolders.vdf" \
|
||||
| jq -r '.libraryfolders[]|select(.apps|has("221100")).path')"
|
||||
if [[ ! $? -eq 0 ]] || [[ -z $steam_path ]]; then
|
||||
logger WARN "Failed to parse Steam path using '$search_path'"
|
||||
return 1
|
||||
fi
|
||||
if [[ ${#paths[@]} -eq 0 ]]; then
|
||||
logger WARN "No valid VDF paths in '$search_path'"
|
||||
return 1
|
||||
fi
|
||||
if [[ ${#paths[@]} -gt 1 ]]; then
|
||||
for path in "${paths[@]}"; do
|
||||
if [[ -d "$path" ]]; then
|
||||
steam_path="$path"
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
steam_path="${paths[0]}"
|
||||
fi
|
||||
logger INFO "Steam path resolved to: $steam_path"
|
||||
}
|
||||
create_config(){
|
||||
@@ -929,7 +895,6 @@ create_config(){
|
||||
unset default_steam_path
|
||||
unset steam_path
|
||||
|
||||
preferred_client="steam"
|
||||
while true; do
|
||||
local player_input="$($steamsafe_zenity \
|
||||
--forms \
|
||||
@@ -990,7 +955,6 @@ create_config(){
|
||||
done
|
||||
}
|
||||
varcheck(){
|
||||
echo "# Checking config file"
|
||||
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 (DayZ was moved or uninstalled). Restart first-time setup now?"
|
||||
if [[ ! -f $config_file ]]; then
|
||||
@@ -1004,7 +968,7 @@ varcheck(){
|
||||
source "$config_file"
|
||||
local workshop_dir="$steam_path/steamapps/workshop/content/$aid"
|
||||
local game_dir="$steam_path/steamapps/common/DayZ"
|
||||
if [[ ! -d $steam_path ]] || [[ ! -d $game_dir ]] || [[ ! $(find "$game_dir" -type f) ]]; then
|
||||
if [[ ! -d $steam_path ]] || [[ ! -d $game_dir ]] || [[ ! $(find $game_dir -type f) ]]; then
|
||||
logger WARN "DayZ path resolved to '$game_dir'"
|
||||
logger WARN "Workshop path resolved to '$workshop_dir'"
|
||||
qdialog "$msg2" "Yes" "Exit"
|
||||
@@ -1015,16 +979,18 @@ varcheck(){
|
||||
create_config
|
||||
return 0
|
||||
fi
|
||||
if [[ $src_path != $(realpath "$0") ]]; then
|
||||
src_path=$(realpath "$0")
|
||||
update_config
|
||||
fi
|
||||
}
|
||||
is_dzg_downloading(){
|
||||
echo "# Checking DayZ"
|
||||
if [[ -d $steam_path ]] && [[ -d $steam_path/downloading/$aid ]]; then
|
||||
logger WARN "DayZ may be scheduling updates"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
is_steam_running(){
|
||||
echo "# Checking Steam"
|
||||
local res=$(ps aux | grep "steamwebhelper" | grep -v grep)
|
||||
if [[ -z $res ]]; then
|
||||
logger WARN "Steam may not be running"
|
||||
@@ -1037,7 +1003,6 @@ get_response_code(){
|
||||
curl -Ls -I -o /dev/null -w "%{http_code}" "$url"
|
||||
}
|
||||
test_connection(){
|
||||
echo "# Testing connection"
|
||||
declare -A hr
|
||||
local res1
|
||||
local res2
|
||||
@@ -1071,7 +1036,6 @@ legacy_cols(){
|
||||
mv $cols_file.new $cols_file
|
||||
}
|
||||
stale_mod_signatures(){
|
||||
echo "# Checking stale mods"
|
||||
[[ ! -f "$versions_file" ]] && return
|
||||
local workshop_dir="$steam_path/steamapps/workshop/content/$aid"
|
||||
if [[ -d $workshop_dir ]]; then
|
||||
@@ -1085,48 +1049,18 @@ stale_mod_signatures(){
|
||||
|
||||
}
|
||||
create_new_links(){
|
||||
echo "# Setting up symlinks"
|
||||
"$func_helper" "update_symlinks"
|
||||
}
|
||||
calc_local_coords(){
|
||||
local ip="$1"
|
||||
[[ ! -f "$geo_helper" ]] && return 1
|
||||
|
||||
IFS="." read -ra split <<< "$ip"
|
||||
[[ ${#split[@]} -ne 4 ]] && return 1
|
||||
|
||||
prefix="^${split[0]}.${split[1]}."
|
||||
readarray -t res < <(grep "$prefix" "$geo_helper")
|
||||
|
||||
for address in "${res[@]}"; do
|
||||
IFS="," read -ra fields <<< "$address"
|
||||
upper="${fields[1]}"
|
||||
IFS="." read -ra upper_digits <<< "$upper"
|
||||
if [[ ${split[2]} -gt ${upper_digits[2]} ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ ${split[2]} -eq ${upper_digits[2]} ]]; then
|
||||
if [[ ${split[3]} -gt ${upper_digits[3]} ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ ${split[3]} -eq ${upper_digits[3]} ]]; then
|
||||
echo "${fields[-2]}" >> "$coords_file"
|
||||
echo "${fields[-1]}" >> "$coords_file"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
if [[ ${split[2]} -lt ${upper_digits[2]} ]]; then
|
||||
echo "${fields[-2]}" >> "$coords_file"
|
||||
echo "${fields[-1]}" >> "$coords_file"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
initial_setup(){
|
||||
setup_dirs
|
||||
setup_state_files
|
||||
depcheck
|
||||
check_pyver
|
||||
test_gobject
|
||||
watcher_deps
|
||||
check_architecture
|
||||
test_connection
|
||||
fetch_helpers
|
||||
fetch_helpers > >(pdialog "Checking helper files")
|
||||
varcheck
|
||||
source "$config_file"
|
||||
lock
|
||||
@@ -1135,12 +1069,14 @@ initial_setup(){
|
||||
check_version
|
||||
check_map_count
|
||||
steam_deps
|
||||
migrate_files
|
||||
stale_symlinks
|
||||
stale_mod_signatures
|
||||
create_new_links
|
||||
local_latlon
|
||||
is_steam_running
|
||||
is_dzg_downloading
|
||||
print_config_vals
|
||||
}
|
||||
uninstall(){
|
||||
_full(){
|
||||
@@ -1242,18 +1178,11 @@ main(){
|
||||
|
||||
set_im_module
|
||||
|
||||
printf "Checking dependencies...\n"
|
||||
setup_dirs
|
||||
setup_state_files
|
||||
depcheck
|
||||
check_pyver
|
||||
test_gobject
|
||||
watcher_deps
|
||||
|
||||
initial_setup > >(pdialog "Initializing setup")
|
||||
printf "Initializing setup...\n"
|
||||
initial_setup
|
||||
|
||||
printf "All OK. Kicking off UI...\n"
|
||||
python3.13 "$ui_helper" "--init-ui" "$version" "$is_steam_deck"
|
||||
python3 "$ui_helper" "--init-ui" "$version" "$is_steam_deck"
|
||||
|
||||
}
|
||||
|
||||
|
||||
+171
-162
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o pipefail
|
||||
version="6.0.5-beta.2"
|
||||
version="6.0.0-beta.8"
|
||||
|
||||
#CONSTANTS
|
||||
aid=221100
|
||||
@@ -51,7 +51,6 @@ _cache_binary="$cache_dir/$prefix.binary"
|
||||
_cache_coords="$cache_path/$prefix.coords"
|
||||
_cache_cooldown="$cache_path/$prefix.cooldown"
|
||||
_cache_lan="$cache_path/$prefix.lan"
|
||||
_cache_src_path="$cache_path/$prefix.src"
|
||||
|
||||
#XDG
|
||||
freedesktop_path="$HOME/.local/share/applications"
|
||||
@@ -88,14 +87,17 @@ steam_api_url="https://steamcommunity.com/dev/apikey"
|
||||
battlemetrics_api_url="https://www.battlemetrics.com/developers"
|
||||
bm_api="https://api.battlemetrics.com/servers"
|
||||
|
||||
steam_cmd="$preferred_client"
|
||||
if [[ $preferred_client == "steam" ]]; then
|
||||
steam_cmd="steam"
|
||||
else
|
||||
steam_cmd="flatpak run com.valvesoftware.Steam"
|
||||
fi
|
||||
|
||||
declare -A funcs=(
|
||||
["Highlight stale"]="find_stale_mods"
|
||||
["Change player name"]="update_config_val"
|
||||
["Change Steam API key"]="update_config_val"
|
||||
["Change Battlemetrics API key"]="update_config_val"
|
||||
["Change client"]="update_config_val"
|
||||
["Change favorite server"]="add_record"
|
||||
["Add server by IP"]="add_record"
|
||||
["Add server by ID"]="add_record"
|
||||
@@ -286,7 +288,7 @@ a2s(){
|
||||
local mode="$3"
|
||||
logger INFO "Querying '$ip:$qport' with mode '$mode'"
|
||||
local res
|
||||
res=$(python3.13 "$query_helper" "$ip" "$qport" "$mode")
|
||||
res=$(python3 "$query_helper" "$ip" "$qport" "$mode")
|
||||
if [[ $? -eq 1 ]]; then
|
||||
res=$(try_fallback "$ip" "$qport" "$mode")
|
||||
if [[ $? -eq 1 ]]; then
|
||||
@@ -309,7 +311,7 @@ is_in_favs(){
|
||||
find_id(){
|
||||
local file="$default_steam_path/config/loginusers.vdf"
|
||||
[[ ! -f $file ]] && return 1
|
||||
local res=$(python3.13 "$helpers_path/vdf2json.py" \
|
||||
local res=$(python3 "$helpers_path/vdf2json.py" \
|
||||
-i "$file" \
|
||||
| jq -r '.users
|
||||
|to_entries[]
|
||||
@@ -338,7 +340,7 @@ list_mods(){
|
||||
name=$(awk -F\" '/name/ {print $2}' "${dir}/meta.cpp")
|
||||
base_dir=$(basename $(readlink -f $game_dir/$symlink))
|
||||
size=$(du -s "$(readlink -f "$game_dir/$symlink")" | awk '{print $1}')
|
||||
size=$(python3.13 -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"
|
||||
done | sort -k1)
|
||||
# user may have manually pruned mods out-of-band
|
||||
@@ -397,7 +399,6 @@ get_dist(){
|
||||
logger INFO "Distance: $dist km"
|
||||
fi
|
||||
}
|
||||
|
||||
query_config(){
|
||||
[[ -n $2 ]] && local key=$2
|
||||
keys=(
|
||||
@@ -423,7 +424,6 @@ query_config(){
|
||||
echo "${!i}"
|
||||
done
|
||||
}
|
||||
|
||||
align_versions_file(){
|
||||
shift
|
||||
local mod="$1"
|
||||
@@ -589,6 +589,9 @@ default_steam_path="$default_steam_path"
|
||||
|
||||
#Preferred Steam launch command (for Flatpak support)
|
||||
preferred_client="$preferred_client"
|
||||
|
||||
#DZGUI source path
|
||||
src_path="$src_path"
|
||||
END
|
||||
}
|
||||
format_version_url(){
|
||||
@@ -642,7 +645,6 @@ download_new_version(){
|
||||
return 1
|
||||
fi
|
||||
local version_url="$(format_version_url)"
|
||||
local src_path="$(< "$_cache_src_path")"
|
||||
mv "$src_path" "$src_path.old"
|
||||
curl -Ls "$version_url" > "$src_path"
|
||||
rc=$?
|
||||
@@ -690,7 +692,6 @@ toggle(){
|
||||
auto_install="1"
|
||||
else
|
||||
auto_install=""
|
||||
rm "$versions_file"
|
||||
fi
|
||||
;;
|
||||
Toggle[[:space:]]debug[[:space:]]mode)
|
||||
@@ -700,6 +701,13 @@ toggle(){
|
||||
debug=""
|
||||
fi
|
||||
;;
|
||||
Toggle[[:space:]]Steam/Flatpak)
|
||||
if [[ $preferred_client == "steam" ]]; then
|
||||
preferred_client="flatpak"
|
||||
else
|
||||
preferred_client="steam"
|
||||
fi
|
||||
;;
|
||||
Toggle[[:space:]]DZGUI[[:space:]]fullscreen[[:space:]]boot)
|
||||
if [[ $fullscreen == "true" ]]; then
|
||||
fullscreen="false"
|
||||
@@ -798,9 +806,6 @@ update_config_val(){
|
||||
local context="$1"
|
||||
local value="$2"
|
||||
case $1 in
|
||||
"Change client")
|
||||
key="preferred_client"
|
||||
;;
|
||||
"Change player name")
|
||||
key="name"
|
||||
if [[ -z "${value// }" ]]; then
|
||||
@@ -826,6 +831,7 @@ update_config_val(){
|
||||
declare -n nr=$key
|
||||
nr="$value"
|
||||
update_config
|
||||
echo "Updated the key '$key' to '$value'"
|
||||
return 80
|
||||
}
|
||||
show_log(){
|
||||
@@ -930,19 +936,13 @@ query_defunct(){
|
||||
<<< "$result" awk '{print $2}'
|
||||
}
|
||||
encode(){
|
||||
echo -n "$1" | md5sum | cut -c -8
|
||||
echo "$1" | md5sum | cut -c -8
|
||||
}
|
||||
compare(){
|
||||
local modlist="$@"
|
||||
diff=$(comm -23 <(<<< "$modlist" sort -u) <(installed_mods | sort))
|
||||
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(){
|
||||
logger INFO "Removing legacy symlinks"
|
||||
|
||||
@@ -1033,10 +1033,7 @@ update_symlinks(){
|
||||
if [[ ! -d "$workshop_dir" ]]; then
|
||||
return
|
||||
fi
|
||||
if [[ ! -d "$game_dir" ]]; then
|
||||
return
|
||||
fi
|
||||
unlink_all
|
||||
legacy_symlinks
|
||||
symlinks
|
||||
}
|
||||
try_fallback(){
|
||||
@@ -1087,42 +1084,41 @@ try_connect(){
|
||||
local appid="$2"
|
||||
local binary="$3"
|
||||
|
||||
IFS=":" read -ra address <<< "$record"
|
||||
local ip
|
||||
local gameport
|
||||
local qport
|
||||
ip=${address[0]}
|
||||
gameport=${address[1]}
|
||||
qport=${address[2]}
|
||||
local ip=$(<<< $record awk -F: '{print $1}')
|
||||
local gameport=$(<<< $record awk -F: '{print $2}')
|
||||
local qport=$(<<< $record awk -F: '{print $3}')
|
||||
|
||||
[[ $appid -eq $exp ]] && echo "$binary" > "$_cache_binary"
|
||||
[[ $appid -eq $exp ]] && echo "$binary" > $_cache_binary
|
||||
|
||||
local remote_mods
|
||||
remote_mods=$(a2s "$ip" "$qport" rules)
|
||||
remote_mods=$(a2s $ip $qport rules)
|
||||
if [[ $? -eq 1 ]]; then
|
||||
printf "Failed to fetch server modlist, possibly timed out"
|
||||
return 1
|
||||
fi
|
||||
logger INFO "Server returned modlist: $(<<< "$remote_mods" tr '\n' ' ')"
|
||||
|
||||
local sanitized_mods
|
||||
sanitized_mods=$(query_defunct "$remote_mods")
|
||||
logger INFO "Server returned modlist: $(<<< $remote_mods tr '\n' ' ')"
|
||||
local sanitized_mods=$(query_defunct "$remote_mods")
|
||||
local diff=$(compare "$sanitized_mods")
|
||||
|
||||
logger INFO "Connection attempt for $ip:$qport"
|
||||
update_history "$record"
|
||||
|
||||
case $auto_install in
|
||||
"") install_mods "$sanitized_mods" "manual" ;;
|
||||
1|2) install_mods "$sanitized_mods" "auto" ;;
|
||||
esac
|
||||
|
||||
# NOTE: clean diff indicates that all requisite mods were downloaded
|
||||
diff=$(compare "$sanitized_mods")
|
||||
if [[ -z $diff ]]; then
|
||||
launch "$ip" "$gameport" "$sanitized_mods" "$appid"
|
||||
if [[ -n $auto_install ]]; then
|
||||
logger INFO "Merging modlists"
|
||||
diff=$(merge_modlists "$diff")
|
||||
diff=$(query_defunct "$diff")
|
||||
fi
|
||||
if [[ -n $diff ]]; then
|
||||
if [[ $(check_architecture) -eq 1 ]] && [[ $(test_display_mode) == "gm" ]]; then
|
||||
printf "Use Desktop Mode to download mods on Steam Deck"
|
||||
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
|
||||
printf "User aborted download process, or some mods may have failed to download. Try connecting again to resync."
|
||||
exit 1
|
||||
launch "$ip" "$gameport" "$sanitized_mods" "$appid"
|
||||
fi
|
||||
}
|
||||
check_architecture(){
|
||||
@@ -1138,15 +1134,13 @@ force_update(){
|
||||
printf "Only available when mod auto-install is ON"
|
||||
return 1
|
||||
fi
|
||||
# NOTE: forcibly regenerate signatures by removing file
|
||||
rm "$versions_file"
|
||||
local mods
|
||||
mods=$(ls -1 "$workshop_dir")
|
||||
install_mods "$mods" "force"
|
||||
local update=$(check_timestamps)
|
||||
manual_mod_install "null" "null" "$update" "null" "force" "null"
|
||||
echo "Finished requesting mod updates."
|
||||
return 0
|
||||
}
|
||||
get_timestamps(){
|
||||
get_local_stamps(){
|
||||
readarray -t modlist < <(printf "%s\n" "$@")
|
||||
local max="${#modlist[@]}"
|
||||
_concat(){
|
||||
@@ -1171,6 +1165,67 @@ update_stamps(){
|
||||
printf "%s\n" "${stamps[$i]}" >> $versions_file
|
||||
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(){
|
||||
readarray -t concat_arr <<< "$@"
|
||||
local id
|
||||
@@ -1212,7 +1267,7 @@ launch(){
|
||||
|
||||
if [[ $debug -eq 1 ]]; then
|
||||
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: %s" "$launch_options"
|
||||
printf "Debug mode: these options would have been used to launch the game: $launch_options"
|
||||
return 0
|
||||
fi
|
||||
echo "$concat" > "$_cache_launch"
|
||||
@@ -1248,121 +1303,75 @@ final_handshake(){
|
||||
printf "\n"
|
||||
return 6
|
||||
}
|
||||
watcher(){
|
||||
local -n to_download="$1"
|
||||
local -n signatures="$2"
|
||||
local mode="$3"
|
||||
|
||||
declare -i i=0
|
||||
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
|
||||
|
||||
until [[ -d $downloads_dir/${mod} ]]; do
|
||||
[[ -f $ex ]] && return 1
|
||||
sleep 0.1s
|
||||
# NOTE: fallback for instantaneous downloads
|
||||
if [[ $mode == "auto" || $mode == "force" ]]; then
|
||||
if [[ -d $workshop_dir/${mod} ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
foreground
|
||||
case $mode in
|
||||
"auto" | "force")
|
||||
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"
|
||||
manual_mod_install(){
|
||||
local ip="$1"
|
||||
local gameport="$2"
|
||||
local diff="$3"
|
||||
local sanitized_mods="$4"
|
||||
local mode="$5"
|
||||
local appid="$6"
|
||||
local ex="$state_path/dzg.watcher"
|
||||
|
||||
[[ -f $ex ]] && rm "$ex"
|
||||
readarray -t stage_mods <<< "$diff"
|
||||
[[ -f $ex ]] && rm $ex
|
||||
|
||||
if [[ -f "$versions_file" ]]; then
|
||||
readarray -t local_mods < "$versions_file"
|
||||
else
|
||||
local_mods=()
|
||||
_watcher(){
|
||||
for((i=0;i<${#stage_mods[@]};i++)); do
|
||||
[[ -f $ex ]] && return 1
|
||||
|
||||
if [[ $mode == "auto" ]] || [[ $mode == "force" ]]; then
|
||||
$steam_cmd "steam://url/CommunityFilePage/${stage_mods[$i]}+workshop_download_item $aid ${stage_mods[$i]}"
|
||||
echo "# Opening workshop page for ${stage_mods[$i]}. If you see no progress, you may be out of disk space."
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
rm "$versions_file"
|
||||
check_timestamps
|
||||
return 0
|
||||
fi
|
||||
|
||||
declare -A mod_signatures
|
||||
local local_id
|
||||
local local_time
|
||||
for mod in "${local_mods[@]}"; do
|
||||
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
|
||||
local diff=$(compare "$sanitized_mods")
|
||||
if [[ -z $diff ]]; then
|
||||
if [[ $mode == "auto" ]]; then
|
||||
rm "$versions_file"
|
||||
check_timestamps
|
||||
fi
|
||||
# NOTE: mod timestamp is out of date
|
||||
local_time="${mod_signatures["$remote_id"]}"
|
||||
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"
|
||||
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
|
||||
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(){
|
||||
pgrep -a gamescope | grep -q "generate-drm-mode"
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#define R 6371
|
||||
#define TO_RAD (3.1415926536 / 180)
|
||||
double dist(double th1, double ph1, double th2, double ph2)
|
||||
{
|
||||
double dx, dy, dz;
|
||||
ph1 -= ph2;
|
||||
ph1 *= TO_RAD, th1 *= TO_RAD, th2 *= TO_RAD;
|
||||
|
||||
dz = sin(th1) - sin(th2);
|
||||
dx = cos(ph1) * cos(th1) - cos(th2);
|
||||
dy = sin(ph1) * cos(th1);
|
||||
return asin(sqrt(dx * dx + dy * dy + dz * dz) / 2) * 2 * R;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
if(argc < 5 || argc > 5){
|
||||
return 1;
|
||||
}
|
||||
float coords[4];
|
||||
for(int i=1;i<5;i++){
|
||||
if(atof(argv[i]) == 0){
|
||||
return 1;
|
||||
}
|
||||
coords[i] = atof(argv[i]);
|
||||
}
|
||||
|
||||
double d = dist(coords[1], coords[2], coords[3], coords[4]);
|
||||
printf("%.1f\n", d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -295,7 +295,7 @@ def get_dayz_version(file: Path) -> DayZVersion | Exception:
|
||||
try:
|
||||
version = get_version(file)
|
||||
except Exception as e:
|
||||
raise e
|
||||
return e
|
||||
patch = str(version.build) + str(version.revision)
|
||||
dz_vers = DayZVersion(version.major, version.minor, int(patch))
|
||||
return dz_vers
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
latlon
|
||||
@@ -1,24 +0,0 @@
|
||||
bin := latlon
|
||||
|
||||
CC = gcc
|
||||
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -Wpedantic
|
||||
CFLAGS += -std=c23
|
||||
CFLAGS += -O3
|
||||
|
||||
LDFLAGS += -lm
|
||||
|
||||
PREFIX ?= $(HOME)/.local/share/dzgui
|
||||
|
||||
all: $(bin)
|
||||
|
||||
install: $(bin)
|
||||
install -Dm 755 $(bin) $(PREFIX)
|
||||
|
||||
$(bin): latlon.c
|
||||
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f $(bin)
|
||||
@@ -1,77 +0,0 @@
|
||||
// This small program computes the distance between two points on the Earths
|
||||
// surface. The algorithm used for computing is called haversine formula.
|
||||
// Source for the algorithm can be found here:
|
||||
// https://en.wikipedia.org/wiki/Haversine_formula
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Earth's radius in meters.
|
||||
#define RADIUS ((12756L / 2.0L) * 1000L)
|
||||
|
||||
// PI natural constant
|
||||
#define PI 3.1415926536L
|
||||
|
||||
// coordinates struct for storing points
|
||||
struct Coordinate {
|
||||
double latitude;
|
||||
double longitude;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Calculates a radian value from an angle
|
||||
*/
|
||||
double radian_from(const double angle) {
|
||||
return (angle * PI) / 180;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the haversine function from an angle in radian
|
||||
*/
|
||||
double haversine(const double angle) { return ((1.0L - cos(angle)) / 2); }
|
||||
|
||||
/**
|
||||
* @brief Calculate the distance between two coordinates
|
||||
*/
|
||||
double great_circle_distance(const struct Coordinate a,
|
||||
const struct Coordinate b) {
|
||||
|
||||
// calculate longitude and latitude differences
|
||||
struct Coordinate diff_coord = {
|
||||
.longitude = a.longitude - b.longitude,
|
||||
.latitude = a.latitude - b.latitude,
|
||||
};
|
||||
|
||||
// calculate haversine(theta) value, where theta is the angle between the
|
||||
// two coordinates
|
||||
double hav_theta = haversine(diff_coord.latitude)
|
||||
+ cos(a.latitude) * cos(b.latitude) * haversine(diff_coord.longitude);
|
||||
|
||||
// calculate distance from radius, and haversine(theta) values
|
||||
double distance = 2 * RADIUS * asin(sqrt(hav_theta));
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc < 5 || argc > 5) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct Coordinate a = {
|
||||
.latitude = radian_from(atof(argv[1])),
|
||||
.longitude = radian_from(atof(argv[2])),
|
||||
};
|
||||
const struct Coordinate b = {
|
||||
.latitude = radian_from(atof(argv[3])),
|
||||
.longitude = radian_from(atof(argv[4])),
|
||||
};
|
||||
|
||||
// Returns the distance in meters.
|
||||
// To pretty-print the result in a consumer of this module, it is
|
||||
// recommended to divide the result by 1,000 and round it.
|
||||
printf("%.1f\n", great_circle_distance(a, b));
|
||||
|
||||
return 0;
|
||||
}
|
||||
+294
-202
File diff suppressed because it is too large.
Load diff
Binary file not shown.
|
Before Width: | Height: | Size: 238 KiB |
Reference in new issue
Block a user