Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a427daabd6 | ||
|
|
f760347334 | ||
|
|
319ab2da9e | ||
|
|
2e6bcd4d15 | ||
|
|
0e22e563f6 | ||
|
|
0a5030c60e | ||
|
|
9e73ec8e60 | ||
|
|
3787c7970d | ||
|
|
e91003979c | ||
|
|
c538ff06ad | ||
|
|
bb9a331e6d | ||
|
|
a1b338c7ee | ||
|
|
785fd1c77b | ||
|
|
d95deb0ea3 | ||
|
|
901261b908 | ||
|
|
4e9ba08a0e | ||
|
|
29d939c06d | ||
|
|
4b79fc99ab | ||
|
|
70f748fd19 | ||
|
|
c8c0bfbce4 | ||
|
|
b664fb70d0 | ||
|
|
f49f9e4358 | ||
|
|
9e1d2e8522 | ||
|
|
91f8c66635 | ||
|
|
f0ae39f5f1 | ||
|
|
1c8710c120 | ||
|
|
de776eb5b5 | ||
|
|
dbc74ccade | ||
|
|
16faf51469 | ||
|
|
fd51ca347e | ||
|
|
8dbb7b05f2 | ||
|
|
20a0c2adc4 | ||
|
|
c342e2d846 | ||
|
|
de5fabf64f | ||
|
|
058122f547 | ||
|
|
0b54937a7e | ||
|
|
5595983b04 | ||
|
|
c3895b1cc7 | ||
|
|
48a0350974 | ||
|
|
0cf150fe9e | ||
|
|
64e28e1372 | ||
|
|
2671e87bc9 | ||
|
|
a050cdfc80 | ||
|
|
db9419f3a7 | ||
|
|
b4273404c1 | ||
|
|
2b6061e428 | ||
|
|
3570e257a5 | ||
|
|
af0448ac15 | ||
|
|
bf5ecc7462 | ||
|
|
04d58987de | ||
|
|
52c3a6950c | ||
|
|
38d375444b | ||
|
|
c5538db60c | ||
|
|
9a39e43af7 | ||
|
|
0c076358cd | ||
|
|
293b99402a | ||
|
|
c04adc15fd | ||
|
|
231aa993f8 | ||
|
|
0b9c60a252 | ||
|
|
920181d284 | ||
|
|
88f40958fb | ||
|
|
76e9470483 | ||
|
|
c9b1ddb572 | ||
|
|
ae28465a96 | ||
|
|
5b3344fa50 | ||
|
|
070275ddbe | ||
|
|
e0327d2d38 | ||
|
|
1c0b9df801 | ||
|
|
ce468d9b37 | ||
|
|
8f5078ebac | ||
|
|
d8b9a6177c | ||
|
|
c590f10a64 | ||
|
|
7ec1bac1f0 | ||
|
|
835c3c4fa1 | ||
|
|
893413cfe1 | ||
|
|
fdeb29c5a9 | ||
|
|
f5a2a6a520 | ||
|
|
286ed612c8 | ||
|
|
1733c70cbd | ||
|
|
f41ae43ee2 | ||
|
|
9d6f2f15f0 | ||
|
|
56989976d4 | ||
|
|
bbc2b5bb2a | ||
|
|
993c6c780f | ||
|
|
94db48b556 | ||
|
|
4b3410c2c4 | ||
|
|
36428bfd69 | ||
|
|
f9fa553351 | ||
|
|
1395082d26 | ||
|
|
1db82407ef | ||
|
|
be0b5a77df | ||
|
|
af9e708915 | ||
|
|
b5a50ae277 | ||
|
|
e092139655 | ||
|
|
96867e8cc3 | ||
|
|
0a5b78da1d | ||
|
|
79e117a0dd | ||
|
|
d4a906066d | ||
|
|
3c41152aa8 | ||
|
|
e384890e9a | ||
|
|
abb6b3f02b | ||
|
|
cdc3e0e05f | ||
|
|
a3026101e0 | ||
|
|
8304eb0a53 | ||
|
|
386702fc8a | ||
|
|
b39ac0f036 | ||
|
|
14c8a1a79b | ||
|
|
e5303cbae0 | ||
|
|
b197c64ce7 | ||
|
|
bcda934f14 | ||
|
|
748ce0a05f | ||
|
|
10de829874 | ||
|
|
994dab8f1e | ||
|
|
cb5b017829 | ||
|
|
536c69988b | ||
|
|
80e88f54ad | ||
|
|
8a248b9cec | ||
|
|
ffe95ef0c5 | ||
|
|
436919c852 | ||
|
|
fd371a30fe | ||
|
|
ea1743ecc3 | ||
|
|
94add8d983 | ||
|
|
f4f58f698f | ||
|
|
76eebbfab6 | ||
|
|
d4352807fe | ||
|
|
46f28abfa0 | ||
|
|
a34dbe09ce | ||
|
|
a6fff2b1af | ||
|
|
74da4a1ad1 | ||
|
|
fd7c306c86 | ||
|
|
4b531a8dca | ||
|
|
206656b675 | ||
|
|
462643e212 | ||
|
|
1912e0c4b0 | ||
|
|
1a49cb6879 | ||
|
|
71d0cacadd | ||
|
|
f83dd8b7e4 | ||
|
|
7ab0d7378a | ||
|
|
905c98c406 | ||
|
|
cfadfb627e | ||
|
|
cad3128945 | ||
|
|
d6b782d836 | ||
|
|
79a18303a2 | ||
|
|
3ecb340ad1 | ||
|
|
2f02ae649e | ||
|
|
4c5e07fe89 | ||
|
|
8d50310c76 | ||
|
|
d81b99be25 | ||
|
|
73af2df381 | ||
|
|
6d21c2710b |
No files matched your search
@@ -1,127 +1,3 @@
|
|||||||
# DZTUI
|
A GUI version of [DZTUI](https://github.com/aclist/dztui) for Linux. Used to list community server details and quick connect to preferred servers by staging mods and concatenating launch options automatically. [Documentation](https://aclist.github.io/dzgui/dzgui.html)
|
||||||
|
|
||||||
A TUI pseudo-browser for listing heads-up information on DayZ community servers, fetching and synchronizing mods, and connecting to these servers automatically without manually setting launch
|
|
||||||
parameters.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Dependencies:
|
|
||||||
|
|
||||||
- `jq`
|
|
||||||
- `column` version with support for the `-o` flag (part of `util-linux`)
|
|
||||||
- `steam`
|
|
||||||
|
|
||||||
## Preparation
|
|
||||||
|
|
||||||
1. Update the sysctl `vm.max_map_count` value (see https://www.protondb.com/app/221100)
|
|
||||||
2. Enable the Steam Beta branch (Steam > Settings > Account > Beta participation)
|
|
||||||
3. Enable as your compatibility tool for the game Proton Experimental, 6.3-8, or later--or repacks based on these
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
User settings are configured at the top of the file in the "CONFIG" section. They are listed below in order of appearance in the file. This step is mandatory. Once the values have been correctly filled in, everything else should work by itself. The file comes with some default values for you for reference.
|
|
||||||
|
|
||||||
Read this carefully. The tool will prompt you if keys are configured incorrectly, but preparing your config correctly will save you time and help you understand how to modify it in the future.
|
|
||||||
|
|
||||||
Ensure that you preserve quotation marks around key values.
|
|
||||||
|
|
||||||
### Basic configuration
|
|
||||||
|
|
||||||
|Key|Meaning|
|
|
||||||
| ------ | ------ |
|
|
||||||
|steam_path|Used as a prefix to simplify interpolation of the `workshop_dir` and `game_dir` keys. If both the `workshop_dir` and `game_dir` path reside under the same install point, you need only set the key `steam_path` with the root directory of the Steam install. If you have the game installed in a path separate from the mods (multiple drives, etc.), you can safely ignore the `steam_path` variable and replace the `steam_path` prefix in the two variables below with their explicit paths.
|
|
||||||
|workshop_dir|The path to Steam workshop content (mods). Always ends in `steamapps/content/221100`.|
|
|
||||||
|game_dir|The path to the DayZ installation. Always ends in `steamapps/common/DayZ`.|
|
|
||||||
|key|Your unique API key; you must register for a free API key at https://www.battlemetrics.com/account/register?after=%2Fdevelopers|
|
|
||||||
|whitelist|A comma-separated list of server IDs you want to browse; look through https://www.battlemetrics.com/servers/dayz and select the ones you like. The server ID is the string of numbers at the end of the URL, e.g., https://www.battlemetrics.com/servers/dayz/12269772 = 12269772|
|
|
||||||
|fav|The server ID of a single server you want to flag as your "favorite" -- a default server to fast connect to when using the `f` keybinding. This value is optional and can be left blank. Note: if using a favorite server, you must include this ID in both the `whitelist` value and in the `fav` value. E.g., if `333` is your favorite server: `whitelist="111,222,333"` and `fav="333"`. Your favorite server will be listed with an arrow next to it in the table. The API enforces a sorting algorithm on requests instead of returning them in serial order, so the favorite server may not always appear in the same place in the list. |
|
|
||||||
|name|Some servers require a profile name; this can be any name of your choice. By default, it is set for you as "player". This value is optional and can be left blank.|
|
|
||||||
|separator|Used to separate fields in the table; can be a single character of your choice. This value is optional and can be left blank if you prefer simple tab justification.|
|
|
||||||
|ping|If set to 1, each of the servers is pinged once before showing the results and a time column is added; if you do not need this option, you can set it to 0 to greatly speed up load time.|
|
|
||||||
|debug|If set to 1, performs a "dry-run" connection and prints the launch parameters that would have been used instead of actually connecting to a server, provided no critical errors occur with mod setup. Doesn't quit, so can be used to perform multiple dry-runs in sequence.|
|
|
||||||
|
|
||||||
## Advanced configuration: automation with steamcmd
|
|
||||||
|
|
||||||
NOTE: This feature is experimental and is still being improved upon.
|
|
||||||
|
|
||||||
The advanced configuration is used in conjunction with the basic configuration settings above, but modifies mod downloading behavior. Note: requires installation of `steamcmd`. This is found in the "STEAMCMD Config" section of the file.
|
|
||||||
|
|
||||||
See https://developer.valvesoftware.com/wiki/SteamCMD for additional details.
|
|
||||||
|
|
||||||
|Key|Meaning|
|
|
||||||
| ------ | ------ |
|
|
||||||
|auto_install_mods|if set to 1, uses steamcmd to automatically stage mods without manual subscription necessary|
|
|
||||||
|steam_cmd_user|the name of the local system user that invokes steamcmd (recommended user is `steam`)|
|
|
||||||
|steam_username|the login handle of the real steam account that owns DayZ (this is required for mods; you cannot anonymously download mods without a license)|
|
|
||||||
|staging_dir|the intermediate path to stage downloaded mods to before moving them to the real user's `workshop_dir`. `/tmp` is used by default (see explanation below).
|
|
||||||
|
|
||||||
### Some explanation of how steamcmd works follows:
|
|
||||||
|
|
||||||
`steamcmd` is chiefly designed for updating content on game servers. As such, it is shipped as a command-line application and is designed to be run by a user isolated from the rest of the system. It allows for programmatic login to a Steam account and fetching/updating content in a headless fashion. While this can be done anonymously for downloading game server content, to download mods tied to an actual game, you need the game license (i.e. own the game). This means you must log in to retrieve mods.
|
|
||||||
|
|
||||||
Valve recommends creating an isolated user called `steam` that is used to invoke `steamcmd` and fetch content. This is a reasonable suggestion and makes sense for a server context in particular. Once logged in, `steamcmd` by design stores and hashes the login credentials to uniquely identify the user and obviate further manual password entry from the same account. After prompting for a password (and 2FA code, where applicable), it won't ask for them again unless the hash is removed or the login user is changed.
|
|
||||||
|
|
||||||
You must create the `steam` user (or some other user of your choice) on the local system, and install `steamcmd` from your repositories or download the upstream binary.
|
|
||||||
|
|
||||||
For our purposes, isolating the user still seems like a good idea, but this introduces a challenge: how to fetch the content as the user `steam` and then make it available to the real user in the least kludgy manner possible? Obviously, if the users are isolated from each other, the `steam` user shouldn't be allowed to wantonly write files to the real user's space, and vice versa, the real user shouldn't be able to go into the `steam` user's space.
|
|
||||||
|
|
||||||
I initially thought making use of a common/shared directory that both users have group permissions to would be good: the `steam` user could fetch the mods, then move them to this common directory, which is set to recursively inherit permissions. The real user then grabs the content out of there and puts it in their real mod path. This seemed overengineered, though, and you have to mess about with group permissions and umasks, and would a user create a totally clean directory for this purpose, as I did, or just set their `$HOME`? It seemed rife with problems. Another alternative here would be to use access control lists (ACL), but, again, this just seemed like overkill, and I didn't like the idea of users wantonly moving files in and out of some unspecified directory, especially if someone chose to set this as an important directory path.
|
|
||||||
|
|
||||||
Eventually, I chose something more streamlined:
|
|
||||||
|
|
||||||
1. We use `sudo` to perform a one-time invocation of `steamcmd` as the `steam` user (`sudo -u $steamcmd_user ...`)
|
|
||||||
2. steamcmd fetches the mods as a concatenated list in one go, and writes them to `/tmp` (`+force_install_dir $staging_dir`). `/tmp` seemed like the ideal choice because, by design, all users can see this directory, and it uses the sticky bit, so it's painless to change ownership of the incoming files to the real user and move them out. Lastly, `/tmp` is the de facto place for ephemeral files, so there is no worry about destructively changing files if the write operation is malformed for some reason--although it is unlikely to be. Note that `steamcmd` does not have great error handling or provide correct return codes even if the wrong credentials are supplied, and likes to write a `steamapps`directory (albeit empty) into the destination directory when failing. Taking this into account, `/tmp` seemed like a good place.
|
|
||||||
3. `sudo` is used to change ownership of the incoming files back to the real user and its effective group id (`sudo chown -R $USER:$gid $staging_dir/steamapps`)
|
|
||||||
4. The individual mod ID directories are copied out of `/tmp` to the real mod path.
|
|
||||||
4. Once finished, the directory leftovers are removed from `/tmp` (`rm -r $staging_dir/steamapps`). The `steamapps` root may contain some files we don't want to conflict with the real workshop path, so we just take the mods, not the whole directory stack. Later invocations of `steamcmd` may fail if there is some detritus in `steamapps`, so it needs to be removed.
|
|
||||||
|
|
||||||
There are other ways of solving this, but in terms of skipping group and user management and keeping things fast and simple, this seems reasonable. At most, the user will be asked to input their Stream credentials once and never again until the hash is revoked, and their password (sudo) once. In addition, mod downloading stops becoming a recurring need once it's been done for a few servers.
|
|
||||||
|
|
||||||
Obviously, those credentials go through `steamcmd` directly to Valve and not through this script. See the function `auto_mod_download()` to see the exact command being used.
|
|
||||||
|
|
||||||
## Usage:
|
|
||||||
|
|
||||||
Run `dztui` and it will populate the table with server info for the server IDs you selected. The column at left shows keybindings. Enter the number of a server and push Return to attempt to connect to it. The connection process checks your installed mods against the server's and will warn you if any are missing. Servers are listed in descending order of player count.
|
|
||||||
|
|
||||||
- Enter `f` to connect to your usual server (the one you marked as favorite above) without having to look through the list.
|
|
||||||
- Enter `l` to print the list of your installed mods.
|
|
||||||
- Enter `q` to quit.
|
|
||||||
|
|
||||||
Under a normal configuration, if mods are missing, links to their Workshop pages will be shown as a list, and you must open these manually and click "Subscribe" in the Steam client and wait for them to download.
|
|
||||||
|
|
||||||
If using the advanced configuration, mods will be auto-downloaded with `steamcmd` in a batch.
|
|
||||||
|
|
||||||
Once mods are finished downloading, you can attempt to reconnect. The mods will be checked for compability again and if the local and remote mod list matches, symlinks to the installed workshop content will be created in the DayZ path.
|
|
||||||
|
|
||||||
Lastly, the launch options and mod list will be concatenated and used to launch the game and connect to the destination server. The tool exits upon a successful connection attempt. Use the `debug` configuration key if you encounter problems and want to see what launch parameters would have been used. This can be useful for manual testing or seeing what mods are on certain servers.
|
|
||||||
|
|
||||||
## Known Issues/Possible Pitfalls:
|
|
||||||
|
|
||||||
- Ubuntu's `column` package may be too old to support setting field separators correctly. (TODO: add separate section detailing how to install and compile package)
|
|
||||||
- The ping attempt is only made once as a fast check with no retries.
|
|
||||||
- It goes without saying, but you need to have a sufficiently wide enough terminal window to justify the text correctly.
|
|
||||||
- There is no pagination, so if there are more servers than lines in your terminal, you are going to have to scroll up.
|
|
||||||
- Servers don't verbosely report the version of mods they are running, so other than checking that the mod exists, we can't easily compare version differences. This means you may get booted on connect if your mod is not up to date. (Shouldn't happen due to Steam updates, but it's theoretically possible if a server is pegged to some older version). If that happens, you could manually install the desired version and reconnect.
|
|
||||||
- The server protocol enforces a maximum length of 64 characters, so server names should never exceed the acceptable width of the table, making truncation unneccessary.
|
|
||||||
- This was not tested with Flatpak steam or Steam native runtime. If there is a particular method of invocation for those, submit an issue.
|
|
||||||
- Official servers do not get indexed by server trackers in the usual manner, so this works only with custom servers. It might be possible to include a manifest of official servers in a future revision, however.
|
|
||||||
- ~~In testing, at least one server behaved strangely despite the correct launch parameters being given and refused to start. (Investigating)~~ **Thanks to the user scandalouss for help in resolving this issue**
|
|
||||||
- You may still encounter weird bugs from DayZ itself due to the unstable nature of the client. (E.g., "User is not connected to Steam" when loading into a map.)
|
|
||||||
- Wasn't tested on esoteric terminal emulators or fancy configs. (Tested against urxvt)
|
|
||||||
|
|
||||||
## Q&A
|
|
||||||
|
|
||||||
Q. Why not use a custom server query API?
|
|
||||||
|
|
||||||
A. It is technically feasible using A2S, but is complicated and offers little benefit other than further automation (no API registration) and slightly more granular control over the server info returned. Still, I would like to include that at some point through a helper file.
|
|
||||||
|
|
||||||
Q. Why not allow browsing all servers in real time?
|
|
||||||
|
|
||||||
A. It greatly complicates the scope. There are 10K+ servers that would have to be queried and some kind of manifest created, to say nothing of sorting, searching, pagination, etc. Having a simple heads-up list of your servers of interest should suffice for most use cases. I am thinking of rewriting this in curses as a fully-featured browser at some point, but we would have to see what improvements are made to the in-game browser and launcher to see if this is maintainable or even necessary in the first place.
|
|
||||||
|
|
||||||
Q. What about adding the field «insert some field name here»?
|
|
||||||
|
|
||||||
A. See above. "Number of players in queue" could be added to help decide whether to join a full server, but this requires a custom API.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
- Clean up logging
|
||||||
|
- Custom query API
|
||||||
|
- Standardize dialogs
|
||||||
|
- Query and connect by IP/port
|
||||||
|
|
||||||
|
## [2.6.0-rc.5] 2022-09-03
|
||||||
|
### Fixed
|
||||||
|
- Make variable local
|
||||||
|
|
||||||
|
## [2.6.0-rc.4] 2022-09-03
|
||||||
|
### Fixed
|
||||||
|
- Use alternate API for direct IP queries
|
||||||
|
|
||||||
|
## [2.6.0-rc.3] 2022-09-03
|
||||||
|
### Changed
|
||||||
|
- Revert to legacy API method
|
||||||
|
|
||||||
|
## [2.6.0-rc.2] 2022-08-31
|
||||||
|
### Added
|
||||||
|
- Validate Steam API key
|
||||||
|
|
||||||
|
## [2.6.0-rc.1] 2022-08-16
|
||||||
|
### Added
|
||||||
|
- Connect to server by IP
|
||||||
|
|
||||||
|
## [2.5.0-rc.2] 2022-08-14
|
||||||
|
### Fixed
|
||||||
|
- Hotfix for server list responses with no next page cursor breaking table
|
||||||
|
|
||||||
|
## [2.5.0-rc.1] 2022-08-14
|
||||||
|
### Changed
|
||||||
|
- More performant path discovery, skip extraneous prompts
|
||||||
|
|
||||||
|
## [2.4.2-rc.5] 2022-08-13
|
||||||
|
### Fixed
|
||||||
|
- Cleaned typos and removed debug code
|
||||||
|
|
||||||
|
## [2.4.2-rc.4] 2022-08-13
|
||||||
|
### Fixed
|
||||||
|
- Clean up legacy symlinks
|
||||||
|
|
||||||
|
## [2.4.2-rc.3] 2022-08-13
|
||||||
|
### Fixed
|
||||||
|
- Alternate symlink method to prevent collisions in IDs
|
||||||
|
|
||||||
|
## [2.4.2-rc.2] 2022-08-10
|
||||||
|
### Fixed
|
||||||
|
- Pass correct query ports to modlist function
|
||||||
|
|
||||||
|
## [2.4.2-rc.1] 2022-08-10
|
||||||
|
### Fixed
|
||||||
|
- Page though API results to list >10 servers
|
||||||
|
|
||||||
|
## [2.4.1-testing] 2022-08-09
|
||||||
|
### Fixed
|
||||||
|
- Hotfix for progress bar breaking table when >9 servers in list
|
||||||
|
|
||||||
|
## [2.4.0-rc.10 - 2.4.0-rc.14] 2022-08-05
|
||||||
|
### Fixed
|
||||||
|
- Miscellaneous backend changes to test deployment of shortcuts to Steam Deck
|
||||||
|
|
||||||
|
## [2.4.0-rc.9] 2022-08-05
|
||||||
|
### Added
|
||||||
|
- Steam Deck artwork
|
||||||
|
|
||||||
|
## [2.4.0-rc.8] 2022-08-04
|
||||||
|
### Fixed
|
||||||
|
- Prevent word splitting of CPU result
|
||||||
|
- Correct path for writing .desktop files
|
||||||
|
|
||||||
|
## [2.4.0-rc.7] 2022-08-04
|
||||||
|
### Fixed
|
||||||
|
- Prevent user from entering invalid entries on first-time setup
|
||||||
|
- Prompt to re-run first-time setup if config is malformed
|
||||||
|
- Better handling of field output from table
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Prototype .desktop file for Steam Deck
|
||||||
|
- Generate bug report logs summarizing local settings
|
||||||
|
|
||||||
|
### Dropped
|
||||||
|
- Deprecated functions
|
||||||
|
|
||||||
|
## [2.4.0-rc.5] 2022-07-31
|
||||||
|
### Changed
|
||||||
|
- Drop download prompt for branch toggle
|
||||||
|
|
||||||
|
## [2.4.0-rc.4] 2022-07-31
|
||||||
|
### Fixed
|
||||||
|
- Source seen_news and debug values when writing new config file
|
||||||
|
|
||||||
|
## [2.4.0-rc.3] 2022-07-31
|
||||||
|
### Fixed
|
||||||
|
- Populate branch value correctly when staging config file
|
||||||
|
|
||||||
|
## [2.4.0-rc.2] 2022-07-31
|
||||||
|
### Fixed
|
||||||
|
- Enforce download when switching branches
|
||||||
|
|
||||||
|
## [2.4.0-rc.1] 2022-07-24
|
||||||
|
### Added
|
||||||
|
- Dependency check for Steam
|
||||||
|
- Delete server from list
|
||||||
|
- News backend for critical updates
|
||||||
|
- Prompt to permanently update sysctl map count
|
||||||
|
- Clean up stale symlinks if mods were deleted
|
||||||
|
- Backported DZTUI mod listing method (includes symlinks)
|
||||||
|
- Backported DZTUI method of encoding symlinks when handling large number of mods
|
||||||
|
- Write dry-run launch options to file when in debug mode
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Prevent garbage in dependency check messages
|
||||||
|
- Send browser to background when opening links
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Couple connect to fav and normal connect to same query function for maintainability
|
||||||
|
- Revert to old issues page index
|
||||||
|
- Hide header on unneeded pages
|
||||||
|
- Better detection of Steam Deck
|
||||||
|
|
||||||
|
## [2.3.0] 2022-07-18
|
||||||
|
### Added
|
||||||
|
- Numbered mod links in browser
|
||||||
|
- Admonition to upgrade versions for bug fixes
|
||||||
|
- Toggle branch between stable/testing
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Hotfix for fav server select on main menu
|
||||||
|
|
||||||
|
## [2.2.1] 2022-07-17
|
||||||
|
### Fixed
|
||||||
|
- Hotfix for upstream API returning malformed modlists
|
||||||
|
- Handle servers with no mods
|
||||||
|
- Fix dialog window depending on browser exit
|
||||||
|
- Remove stray newlines in config file
|
||||||
|
|
||||||
|
## [2.2.0] 2022-06-22
|
||||||
|
### Added
|
||||||
|
- Toggle debug mode in-app
|
||||||
|
|
||||||
|
## [2.1.0] 2022-06-19
|
||||||
|
### Changed
|
||||||
|
- Updated link to new documentation
|
||||||
|
|
||||||
|
## [2.0.3] 2022-06-17
|
||||||
|
### Fixed
|
||||||
|
- Safer expansion of originating script path
|
||||||
|
|
||||||
|
## [2.0.2] 2022-06-16
|
||||||
|
### Fixed
|
||||||
|
- Remove enforced runtime check of workshop path
|
||||||
|
|
||||||
|
## [2.0.2] 2022-06-16
|
||||||
|
### Fixed
|
||||||
|
- Expansion of Steam path prefix when default path was found
|
||||||
|
|
||||||
|
## [2.0.1] 2022-06-16
|
||||||
|
### Fixed
|
||||||
|
- Regenerate mod links file in browser when clicking dialog
|
||||||
|
- Reset whitelist when canceling one-shot (fav) mode
|
||||||
|
|
||||||
|
## [2.0.0] 2022-06-15
|
||||||
|
### Added
|
||||||
|
- Attempt to find DayZ path and write to config on first launch
|
||||||
|
- Merge existing config values into new config format when upgrading version
|
||||||
|
- Dynamically detect Steam Deck and set launch parameters
|
||||||
|
- Add "gametime" column to server list
|
||||||
|
- One-shot mode to open mod links in browser if using desktop
|
||||||
|
- Add favorite server from main menu
|
||||||
|
- Update favorite server changes in real time
|
||||||
|
- Add link to help pages from main menu
|
||||||
|
- Add link to changelog from main menu
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Don't require duplication of fav server in whitelist
|
||||||
|
- More permissive truncation of long server names (50 char limit)
|
||||||
|
- Render mod list as a scrollable menu
|
||||||
|
- Reword errors for greater verbosity
|
||||||
|
- Initial support of granular error handling for API response codes
|
||||||
|
- Move extended path variables out of user config
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Check if mod dir is sane before listing mods
|
||||||
|
- Prevent favorite server launch if none set
|
||||||
|
- Reset server list to entire whitelist if canceling out of fav connect
|
||||||
|
- Do not load table on empty API response and warn user
|
||||||
|
- Suppress stderr cruft in logs and use logger instead
|
||||||
|
|
||||||
|
## [1.2.1] 2022-06-12
|
||||||
|
### Fixed
|
||||||
|
- Print the entire changelog
|
||||||
|
- Add confirmation dialog before run
|
||||||
|
|
||||||
|
## [1.2.0] 2022-06-12
|
||||||
|
### Changed
|
||||||
|
- Mod validation process now uses faster, single-pass API query
|
||||||
|
- Improved logger output when setting fav server
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- In-app changelog
|
||||||
|
|
||||||
|
## [1.1.2] 2022-06-08
|
||||||
|
### Fixed
|
||||||
|
- Fix array used for mod concatenation; fetch post-sanitized list of mods
|
||||||
|
|
||||||
|
## [1.1.1] 2022-06-05
|
||||||
|
### Fixed
|
||||||
|
- Stricter regex to parse upstream version number
|
||||||
|
|
||||||
|
## [1.1.0] 2022-06-05
|
||||||
|
### Added
|
||||||
|
- Main menu: fav server label on header
|
||||||
|
- Main menu: add servers by ID directly into config file
|
||||||
|
- Main menu: link to report a bug
|
||||||
|
- Main menu: quick connect to fav server
|
||||||
|
- Connect: mod compatibility check
|
||||||
|
- Connect: mod download prompt
|
||||||
|
- Connect: mod auto symlinks
|
||||||
|
- New version download prompt
|
||||||
|
- Additional visualization of progress/menus
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Menu recursion when navigating backwards
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Reduced ping timeout interval
|
||||||
@@ -0,0 +1,427 @@
|
|||||||
|
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
|
||||||
|
/* Uncomment the following line when using as a custom stylesheet */
|
||||||
|
/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
|
||||||
|
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
|
||||||
|
h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 {color: #8a1414 !important}
|
||||||
|
a{background:none}
|
||||||
|
a:focus{outline:thin dotted}
|
||||||
|
a:active,a:hover{outline:0}
|
||||||
|
h1{font-size:2em;margin:.67em 0}
|
||||||
|
b,strong{font-weight:bold}
|
||||||
|
abbr{font-size:.9em}
|
||||||
|
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
|
||||||
|
dfn{font-style:italic}
|
||||||
|
hr{height:0}
|
||||||
|
mark{background:#ff0;color:#000}
|
||||||
|
code,kbd,pre,samp{font-family:monospace;font-size:1em}
|
||||||
|
pre{white-space:pre-wrap}
|
||||||
|
q{quotes:"\201C" "\201D" "\2018" "\2019"}
|
||||||
|
small{font-size:80%}
|
||||||
|
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||||||
|
sup{top:-.5em}
|
||||||
|
sub{bottom:-.25em}
|
||||||
|
img{border:0}
|
||||||
|
svg:not(:root){overflow:hidden}
|
||||||
|
figure{margin:0}
|
||||||
|
audio,video{display:inline-block}
|
||||||
|
audio:not([controls]){display:none;height:0}
|
||||||
|
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
|
||||||
|
legend{border:0;padding:0}
|
||||||
|
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
|
||||||
|
button,input{line-height:normal}
|
||||||
|
button,select{text-transform:none}
|
||||||
|
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
|
||||||
|
button[disabled],html input[disabled]{cursor:default}
|
||||||
|
input[type=checkbox],input[type=radio]{padding:0}
|
||||||
|
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
|
||||||
|
textarea{overflow:auto;vertical-align:top}
|
||||||
|
table{border-collapse:collapse;border-spacing:0}
|
||||||
|
*,::before,::after{box-sizing:border-box}
|
||||||
|
html,body{font-size:100%}
|
||||||
|
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
|
||||||
|
a:hover{cursor:pointer}
|
||||||
|
img,object,embed{max-width:100%;height:auto}
|
||||||
|
object,embed{height:100%}
|
||||||
|
img{-ms-interpolation-mode:bicubic}
|
||||||
|
.left{float:left!important}
|
||||||
|
.right{float:right!important}
|
||||||
|
.text-left{text-align:left!important}
|
||||||
|
.text-right{text-align:right!important}
|
||||||
|
.text-center{text-align:center!important}
|
||||||
|
.text-justify{text-align:justify!important}
|
||||||
|
.hide{display:none}
|
||||||
|
img,object,svg{display:inline-block;vertical-align:middle}
|
||||||
|
textarea{height:auto;min-height:50px}
|
||||||
|
select{width:100%}
|
||||||
|
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
|
||||||
|
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
|
||||||
|
a{color:#2156a5;text-decoration:underline;line-height:inherit}
|
||||||
|
a:hover,a:focus{color:#1d4b8f}
|
||||||
|
a img{border:0}
|
||||||
|
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
|
||||||
|
p aside{font-size:.875em;line-height:1.35;font-style:italic}
|
||||||
|
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
|
||||||
|
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
|
||||||
|
h1{font-size:2.125em}
|
||||||
|
h2{font-size:1.6875em}
|
||||||
|
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
|
||||||
|
h4,h5{font-size:1.125em}
|
||||||
|
h6{font-size:1em}
|
||||||
|
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
|
||||||
|
em,i{font-style:italic;line-height:inherit}
|
||||||
|
strong,b{font-weight:bold;line-height:inherit}
|
||||||
|
small{font-size:60%;line-height:inherit}
|
||||||
|
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
|
||||||
|
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
|
||||||
|
ul,ol{margin-left:1.5em}
|
||||||
|
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
|
||||||
|
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
|
||||||
|
ul.square{list-style-type:square}
|
||||||
|
ul.circle{list-style-type:circle}
|
||||||
|
ul.disc{list-style-type:disc}
|
||||||
|
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
|
||||||
|
dl dt{margin-bottom:.3125em;font-weight:bold}
|
||||||
|
dl dd{margin-bottom:1.25em}
|
||||||
|
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
|
||||||
|
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
|
||||||
|
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
|
||||||
|
h1{font-size:2.75em}
|
||||||
|
h2{font-size:2.3125em}
|
||||||
|
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
|
||||||
|
h4{font-size:1.4375em}}
|
||||||
|
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
|
||||||
|
table thead,table tfoot{background:#f7f8f7}
|
||||||
|
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
|
||||||
|
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
|
||||||
|
table tr.even,table tr.alt{background:#f8f8f7}
|
||||||
|
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
|
||||||
|
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
|
||||||
|
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
|
||||||
|
.center{margin-left:auto;margin-right:auto}
|
||||||
|
.stretch{width:100%}
|
||||||
|
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
|
||||||
|
.clearfix::after,.float-group::after{clear:both}
|
||||||
|
:not(pre).nobreak{word-wrap:normal}
|
||||||
|
:not(pre).nowrap{white-space:nowrap}
|
||||||
|
:not(pre).pre-wrap{white-space:pre-wrap}
|
||||||
|
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
|
||||||
|
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
|
||||||
|
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
|
||||||
|
pre>code{display:block}
|
||||||
|
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
|
||||||
|
em em{font-style:normal}
|
||||||
|
strong strong{font-weight:400}
|
||||||
|
.keyseq{color:rgba(51,51,51,.8)}
|
||||||
|
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
||||||
|
.keyseq kbd:first-child{margin-left:0}
|
||||||
|
.keyseq kbd:last-child{margin-right:0}
|
||||||
|
.menuseq,.menuref{color:#000}
|
||||||
|
.menuseq b:not(.caret),.menuref{font-weight:inherit}
|
||||||
|
.menuseq{word-spacing:-.02em}
|
||||||
|
.menuseq b.caret{font-size:1.25em;line-height:.8}
|
||||||
|
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
|
||||||
|
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
|
||||||
|
b.button::before{content:"[";padding:0 3px 0 2px}
|
||||||
|
b.button::after{content:"]";padding:0 2px 0 3px}
|
||||||
|
p a>code:hover{color:rgba(0,0,0,.9)}
|
||||||
|
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
|
||||||
|
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
|
||||||
|
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
|
||||||
|
#content{margin-top:1.25em}
|
||||||
|
#content::before{content:none}
|
||||||
|
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
|
||||||
|
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
|
||||||
|
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
|
||||||
|
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
|
||||||
|
#header .details span:first-child{margin-left:-.125em}
|
||||||
|
#header .details span.email a{color:rgba(0,0,0,.85)}
|
||||||
|
#header .details br{display:none}
|
||||||
|
#header .details br+span::before{content:"\00a0\2013\00a0"}
|
||||||
|
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
|
||||||
|
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
|
||||||
|
#header #revnumber{text-transform:capitalize}
|
||||||
|
#header #revnumber::after{content:"\00a0"}
|
||||||
|
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
|
||||||
|
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
|
||||||
|
#toc>ul{margin-left:.125em}
|
||||||
|
#toc ul.sectlevel0>li>a{font-style:italic}
|
||||||
|
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
|
||||||
|
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
|
||||||
|
#toc li{line-height:1.3334;margin-top:.3334em}
|
||||||
|
#toc a{text-decoration:none}
|
||||||
|
#toc a:active{text-decoration:underline}
|
||||||
|
#toctitle{color:#7a2518;font-size:1.2em}
|
||||||
|
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
|
||||||
|
body.toc2{padding-left:15em;padding-right:0}
|
||||||
|
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
|
||||||
|
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
|
||||||
|
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
|
||||||
|
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
|
||||||
|
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
|
||||||
|
body.toc2.toc-right{padding-left:0;padding-right:15em}
|
||||||
|
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
|
||||||
|
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
|
||||||
|
#toc.toc2{width:20em}
|
||||||
|
#toc.toc2 #toctitle{font-size:1.375em}
|
||||||
|
#toc.toc2>ul{font-size:.95em}
|
||||||
|
#toc.toc2 ul ul{padding-left:1.25em}
|
||||||
|
body.toc2.toc-right{padding-left:0;padding-right:20em}}
|
||||||
|
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
|
||||||
|
#content #toc>:first-child{margin-top:0}
|
||||||
|
#content #toc>:last-child{margin-bottom:0}
|
||||||
|
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
|
||||||
|
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
|
||||||
|
#content{margin-bottom:.625em}
|
||||||
|
.sect1{padding-bottom:.625em}
|
||||||
|
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
|
||||||
|
.sect1{padding-bottom:1.25em}}
|
||||||
|
.sect1:last-child{padding-bottom:0}
|
||||||
|
.sect1+.sect1{border-top:1px solid #e7e7e9}
|
||||||
|
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
|
||||||
|
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
|
||||||
|
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
|
||||||
|
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
|
||||||
|
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
|
||||||
|
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
|
||||||
|
details{margin-left:1.25rem}
|
||||||
|
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
|
||||||
|
details>summary::-webkit-details-marker{display:none}
|
||||||
|
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
|
||||||
|
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
|
||||||
|
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
|
||||||
|
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
|
||||||
|
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
|
||||||
|
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
|
||||||
|
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
|
||||||
|
.admonitionblock>table td.icon{text-align:center;width:80px}
|
||||||
|
.admonitionblock>table td.icon img{max-width:none}
|
||||||
|
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
|
||||||
|
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
|
||||||
|
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
|
||||||
|
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
|
||||||
|
.exampleblock>.content>:first-child{margin-top:0}
|
||||||
|
.exampleblock>.content>:last-child{margin-bottom:0}
|
||||||
|
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
|
||||||
|
.sidebarblock>:first-child{margin-top:0}
|
||||||
|
.sidebarblock>:last-child{margin-bottom:0}
|
||||||
|
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
|
||||||
|
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
|
||||||
|
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
|
||||||
|
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
|
||||||
|
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
|
||||||
|
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
|
||||||
|
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
|
||||||
|
.listingblock>.content{position:relative}
|
||||||
|
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
|
||||||
|
.listingblock:hover code[data-lang]::before{display:block}
|
||||||
|
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
|
||||||
|
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
|
||||||
|
.listingblock pre.highlightjs{padding:0}
|
||||||
|
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
|
||||||
|
.listingblock pre.prettyprint{border-width:0}
|
||||||
|
.prettyprint{background:#f7f7f8}
|
||||||
|
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
|
||||||
|
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
|
||||||
|
pre.prettyprint li code[data-lang]::before{opacity:1}
|
||||||
|
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
|
||||||
|
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
|
||||||
|
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
|
||||||
|
table.linenotable td.code{padding-left:.75em}
|
||||||
|
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
||||||
|
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
|
||||||
|
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
|
||||||
|
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
|
||||||
|
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
|
||||||
|
.quoteblock blockquote{margin:0;padding:0;border:0}
|
||||||
|
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
|
||||||
|
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
|
||||||
|
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
|
||||||
|
.verseblock{margin:0 1em 1.25em}
|
||||||
|
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
|
||||||
|
.verseblock pre strong{font-weight:400}
|
||||||
|
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
|
||||||
|
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
|
||||||
|
.quoteblock .attribution br,.verseblock .attribution br{display:none}
|
||||||
|
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
|
||||||
|
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
|
||||||
|
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
|
||||||
|
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
|
||||||
|
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
|
||||||
|
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
|
||||||
|
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
|
||||||
|
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
|
||||||
|
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
|
||||||
|
p.tableblock:last-child{margin-bottom:0}
|
||||||
|
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
|
||||||
|
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
|
||||||
|
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
|
||||||
|
table.grid-all>*>tr>*{border-width:1px}
|
||||||
|
table.grid-cols>*>tr>*{border-width:0 1px}
|
||||||
|
table.grid-rows>*>tr>*{border-width:1px 0}
|
||||||
|
table.frame-all{border-width:1px}
|
||||||
|
table.frame-ends{border-width:1px 0}
|
||||||
|
table.frame-sides{border-width:0 1px}
|
||||||
|
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
|
||||||
|
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
|
||||||
|
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
|
||||||
|
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
|
||||||
|
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
|
||||||
|
th.halign-left,td.halign-left{text-align:left}
|
||||||
|
th.halign-right,td.halign-right{text-align:right}
|
||||||
|
th.halign-center,td.halign-center{text-align:center}
|
||||||
|
th.valign-top,td.valign-top{vertical-align:top}
|
||||||
|
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
|
||||||
|
th.valign-middle,td.valign-middle{vertical-align:middle}
|
||||||
|
table thead th,table tfoot th{font-weight:bold}
|
||||||
|
tbody tr th{background:#f7f8f7}
|
||||||
|
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
|
||||||
|
p.tableblock>code:only-child{background:none;padding:0}
|
||||||
|
p.tableblock{font-size:1em}
|
||||||
|
ol{margin-left:1.75em}
|
||||||
|
ul li ol{margin-left:1.5em}
|
||||||
|
dl dd{margin-left:1.125em}
|
||||||
|
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
|
||||||
|
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
|
||||||
|
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
|
||||||
|
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
|
||||||
|
ul.unstyled,ol.unstyled{margin-left:0}
|
||||||
|
li>p:empty:only-child::before{content:"";display:inline-block}
|
||||||
|
ul.checklist>li>p:first-child{margin-left:-1em}
|
||||||
|
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
|
||||||
|
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
|
||||||
|
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
|
||||||
|
ul.inline>li{margin-left:1.25em}
|
||||||
|
.unstyled dl dt{font-weight:400;font-style:normal}
|
||||||
|
ol.arabic{list-style-type:decimal}
|
||||||
|
ol.decimal{list-style-type:decimal-leading-zero}
|
||||||
|
ol.loweralpha{list-style-type:lower-alpha}
|
||||||
|
ol.upperalpha{list-style-type:upper-alpha}
|
||||||
|
ol.lowerroman{list-style-type:lower-roman}
|
||||||
|
ol.upperroman{list-style-type:upper-roman}
|
||||||
|
ol.lowergreek{list-style-type:lower-greek}
|
||||||
|
.hdlist>table,.colist>table{border:0;background:none}
|
||||||
|
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
|
||||||
|
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
|
||||||
|
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
|
||||||
|
td.hdlist2{word-wrap:anywhere}
|
||||||
|
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
|
||||||
|
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
|
||||||
|
.colist td:not([class]):first-child img{max-width:none}
|
||||||
|
.colist td:not([class]):last-child{padding:.25em 0}
|
||||||
|
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
|
||||||
|
.imageblock.left{margin:.25em .625em 1.25em 0}
|
||||||
|
.imageblock.right{margin:.25em 0 1.25em .625em}
|
||||||
|
.imageblock>.title{margin-bottom:0}
|
||||||
|
.imageblock.thumb,.imageblock.th{border-width:6px}
|
||||||
|
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
|
||||||
|
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
|
||||||
|
.image.left{margin-right:.625em}
|
||||||
|
.image.right{margin-left:.625em}
|
||||||
|
a.image{text-decoration:none;display:inline-block}
|
||||||
|
a.image object{pointer-events:none}
|
||||||
|
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
|
||||||
|
sup.footnote a,sup.footnoteref a{text-decoration:none}
|
||||||
|
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
|
||||||
|
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
|
||||||
|
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
|
||||||
|
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
|
||||||
|
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
|
||||||
|
#footnotes .footnote:last-of-type{margin-bottom:0}
|
||||||
|
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
|
||||||
|
div.unbreakable{page-break-inside:avoid}
|
||||||
|
.big{font-size:larger}
|
||||||
|
.small{font-size:smaller}
|
||||||
|
.underline{text-decoration:underline}
|
||||||
|
.overline{text-decoration:overline}
|
||||||
|
.line-through{text-decoration:line-through}
|
||||||
|
.aqua{color:#00bfbf}
|
||||||
|
.aqua-background{background:#00fafa}
|
||||||
|
.black{color:#000}
|
||||||
|
.black-background{background:#000}
|
||||||
|
.blue{color:#0000bf}
|
||||||
|
.blue-background{background:#0000fa}
|
||||||
|
.fuchsia{color:#bf00bf}
|
||||||
|
.fuchsia-background{background:#fa00fa}
|
||||||
|
.gray{color:#606060}
|
||||||
|
.gray-background{background:#7d7d7d}
|
||||||
|
.green{color:#006000}
|
||||||
|
.green-background{background:#007d00}
|
||||||
|
.lime{color:#00bf00}
|
||||||
|
.lime-background{background:#00fa00}
|
||||||
|
.maroon{color:#600000}
|
||||||
|
.maroon-background{background:#7d0000}
|
||||||
|
.navy{color:#000060}
|
||||||
|
.navy-background{background:#00007d}
|
||||||
|
.olive{color:#606000}
|
||||||
|
.olive-background{background:#7d7d00}
|
||||||
|
.purple{color:#600060}
|
||||||
|
.purple-background{background:#7d007d}
|
||||||
|
.red{color:#bf0000}
|
||||||
|
.red-background{background:#fa0000}
|
||||||
|
.silver{color:#909090}
|
||||||
|
.silver-background{background:#bcbcbc}
|
||||||
|
.teal{color:#006060}
|
||||||
|
.teal-background{background:#007d7d}
|
||||||
|
.white{color:#bfbfbf}
|
||||||
|
.white-background{background:#fafafa}
|
||||||
|
.yellow{color:#bfbf00}
|
||||||
|
.yellow-background{background:#fafa00}
|
||||||
|
span.icon>.fa{cursor:default}
|
||||||
|
a span.icon>.fa{cursor:inherit}
|
||||||
|
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
|
||||||
|
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
|
||||||
|
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
|
||||||
|
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
|
||||||
|
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
|
||||||
|
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
|
||||||
|
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
||||||
|
.conum[data-value] *{color:#fff!important}
|
||||||
|
.conum[data-value]+b{display:none}
|
||||||
|
.conum[data-value]::after{content:attr(data-value)}
|
||||||
|
pre .conum[data-value]{position:relative;top:-.125em}
|
||||||
|
b.conum *{color:inherit!important}
|
||||||
|
.conum:not([data-value]):empty{display:none}
|
||||||
|
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
|
||||||
|
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
|
||||||
|
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
|
||||||
|
p,blockquote,dt,td.content,span.alt,summary{font-size:1.0625rem}
|
||||||
|
p{margin-bottom:1.25rem}
|
||||||
|
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
|
||||||
|
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
|
||||||
|
.print-only{display:none!important}
|
||||||
|
@page{margin:1.25cm .75cm}
|
||||||
|
@media print{*{box-shadow:none!important;text-shadow:none!important}
|
||||||
|
html{font-size:80%}
|
||||||
|
a{color:inherit!important;text-decoration:underline!important}
|
||||||
|
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
|
||||||
|
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
|
||||||
|
abbr[title]{border-bottom:1px dotted}
|
||||||
|
abbr[title]::after{content:" (" attr(title) ")"}
|
||||||
|
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
|
||||||
|
thead{display:table-header-group}
|
||||||
|
svg{max-width:100%}
|
||||||
|
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
|
||||||
|
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
|
||||||
|
#header,#content,#footnotes,#footer{max-width:none}
|
||||||
|
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
|
||||||
|
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
|
||||||
|
body.book #header{text-align:center}
|
||||||
|
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
|
||||||
|
body.book #header .details{border:0!important;display:block;padding:0!important}
|
||||||
|
body.book #header .details span:first-child{margin-left:0!important}
|
||||||
|
body.book #header .details br{display:block}
|
||||||
|
body.book #header .details br+span::before{content:none!important}
|
||||||
|
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
|
||||||
|
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
|
||||||
|
.listingblock code[data-lang]::before{display:block}
|
||||||
|
#footer{padding:0 .9375em}
|
||||||
|
.hide-on-print{display:none!important}
|
||||||
|
.print-only{display:block!important}
|
||||||
|
.hide-for-print{display:none!important}
|
||||||
|
.show-for-print{display:inherit!important}}
|
||||||
|
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
|
||||||
|
.sect1{padding:0!important}
|
||||||
|
.sect1+.sect1{border:0}
|
||||||
|
#footer{background:none}
|
||||||
|
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
|
||||||
|
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
|
||||||
@@ -0,0 +1,291 @@
|
|||||||
|
= DZGUI documentation
|
||||||
|
DayZ community server graphical launcher for Linux | Last updated: 2022-08-05
|
||||||
|
:nofooter:
|
||||||
|
:toc: left
|
||||||
|
:stylesheet: custom.css
|
||||||
|
|
||||||
|
== What this is
|
||||||
|
A GUI version of https://github.com/aclist/dztui[DZTUI] for Linux. Used to list community server details and quick connect to preferred servers by staging mods and concatenating launch options automatically.
|
||||||
|
|
||||||
|
DZGUI contains some expanded functionality that will eventually be backported to DZTUI. It is intended to be more of a user-friendly, turnkey solution for graphical desktop environments, and could also be used on the Steam Deck or similar devices.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
== Setup
|
||||||
|
=== Dependencies
|
||||||
|
If not already installed, the below can be found in your system's package manager.
|
||||||
|
|
||||||
|
- `curl`
|
||||||
|
- `jq`
|
||||||
|
- `zenity`
|
||||||
|
- `steam`
|
||||||
|
|
||||||
|
|
||||||
|
=== Preparation
|
||||||
|
. Download DZGUI and make it executable:
|
||||||
|
|
||||||
|
**Automatic method (skip to 3 below when complete)**
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -s "https://raw.githubusercontent.com/aclist/dztui/testing/install.sh" | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
**Manual method**
|
||||||
|
|
||||||
|
```
|
||||||
|
chmod +x dzgui.sh
|
||||||
|
```
|
||||||
|
[start=2]
|
||||||
|
. Update the `vm.max_map_count` value (see https://www.protondb.com/app/221100)
|
||||||
|
|
||||||
|
Ephemeral method:
|
||||||
|
```
|
||||||
|
sudo sysctl -w vm.max_map_count=1048576
|
||||||
|
```
|
||||||
|
|
||||||
|
Persistent method:
|
||||||
|
```
|
||||||
|
echo 'vm.max_map_count=1048576' | sudo tee /etc/sysctl.d/dayz.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
If it detects an incorrect map count value, DZGUI will prompt you to permanently update the map count value when starting up.
|
||||||
|
|
||||||
|
[start=3]
|
||||||
|
. Steam account with DayZ license
|
||||||
|
. Enable a Proton version ≥ `6.8` (or use Experimental) in the **Compatibility** field of the game's right-click options.
|
||||||
|
|
||||||
|
|
||||||
|
=== API key & server IDs
|
||||||
|
1. Register for an API key at https://www.battlemetrics.com/account/register?after=%2Fdevelopers[BattleMetrics] (free)
|
||||||
|
2. From the **Personal Access Tokens** area, Select **New Token**
|
||||||
|
3. Give the token any name in the field at the top
|
||||||
|
4. Leave all options **unchecked** and scroll to the bottom, select **Create Token**
|
||||||
|
5. Copy the access token for later use (see below). This is the unique token you will use to query servers.
|
||||||
|
6. Use the https://www.battlemetrics.com/servers/dayz[DayZ server browser] to find servers of interest (proximity, player count, rules, etc.)
|
||||||
|
7. Each server has a unique ID. This is the string of numbers at the end of the URL. Copy these IDs. For example, in the URL https://www.battlemetrics.com/servers/dayz/8039514, the ID is `8039514`.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
You will be prompted to enter these IDs when starting the app, so you could refer to them in another window while you complete setup. More IDs can be added later.
|
||||||
|
|
||||||
|
|
||||||
|
=== First-time launch
|
||||||
|
|
||||||
|
1. DZGUI can be launched one of two ways.
|
||||||
|
|
||||||
|
**From the terminal:**
|
||||||
|
|
||||||
|
```
|
||||||
|
./dzgui.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Launching from the terminal gives more verbose information, and can be a good way of troubleshooting problems.
|
||||||
|
|
||||||
|
**From the shortcut shipped with the application:**
|
||||||
|
|
||||||
|
*If using a desktop environment based on the Freedesktop specification
|
||||||
|
|
||||||
|
- Located under the "Games" category of your system's applications list.
|
||||||
|
- Via the DZGUI desktop shortcut (Steam Deck only)
|
||||||
|
|
||||||
|
[start=2]
|
||||||
|
2. Follow the menu prompts given by the app. You will be asked to provide:
|
||||||
|
|
||||||
|
- API key (see above)
|
||||||
|
- Player name (a generic handle, required by some servers)
|
||||||
|
- At least one server ID
|
||||||
|
|
||||||
|
DZGUI will then attempt to locate your default Steam installation and DayZ path. If it detects multiple paths, you will be given a list to choose from.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
If the path was not detected correctly, you can manually edit the config file at `$HOME/.config/dztui/dztuirc`.
|
||||||
|
|
||||||
|
=== Steam integration & artwork
|
||||||
|
|
||||||
|
DZGUI can be added to Steam as a "non-Steam game" in order to facilitate integration with Steam Deck or desktop environments.
|
||||||
|
|
||||||
|
1. Launch Steam in the "Large" view.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
Steam Deck: you must switch to "Desktop Mode" and launch Steam from the desktop.
|
||||||
|
|
||||||
|
[start=2]
|
||||||
|
2. Select **Add a Game** > **Add a Non-Steam Game** from the lower left-hand corner.
|
||||||
|
|
||||||
|
image::https://github.com/aclist/dztui/raw/testing/images/tutorial/01.png[01,500]
|
||||||
|
|
||||||
|
[start=3]
|
||||||
|
3. Navigate to `$HOME/.local/share/applications/` and select `dzgui.desktop`
|
||||||
|
4. Select **Add Selected Programs**.
|
||||||
|
|
||||||
|
The application also ships with Steam cover artwork. It is located under:
|
||||||
|
|
||||||
|
```
|
||||||
|
$HOME/.local/share/dzgui
|
||||||
|
```
|
||||||
|
|
||||||
|
The artwork consists of four parts:
|
||||||
|
|
||||||
|
1. Grid: a vertical "box art" grid used on library pages
|
||||||
|
2. Hero: a large horizontal banner used on the app's details page
|
||||||
|
3. Logo: a transparent icon used to remove Steam's default app text
|
||||||
|
4. dzgui: used by freedesktop shortcut to generate a desktop icon; not intended for the user
|
||||||
|
|
||||||
|
Updating the artwork:
|
||||||
|
|
||||||
|
1. Navigate to the app's details page and right-click the blank image header at the top.
|
||||||
|
|
||||||
|
image::https://github.com/aclist/dztui/raw/testing/images/tutorial/03.png[03,700]
|
||||||
|
|
||||||
|
[start=2]
|
||||||
|
2. Select **Set Custom Background**
|
||||||
|
3. Select to display All Files from the File type dropdown
|
||||||
|
4. Navigate to the artwork path described above and select `hero.png`.
|
||||||
|
5. Next, right-click the image background and select **Set Custom Logo**.
|
||||||
|
|
||||||
|
image::https://github.com/aclist/dztui/raw/testing/images/tutorial/04.png[04,700]
|
||||||
|
|
||||||
|
[start=5]
|
||||||
|
5. Navigate to the same path and select `logo.png`. Notice that this removes the redundant app name that occluded the image.
|
||||||
|
|
||||||
|
image::https://github.com/aclist/dztui/raw/testing/images/tutorial/05.png[05,700]
|
||||||
|
|
||||||
|
[start=6]
|
||||||
|
6. Next, navigate to your Library index (looks like a bookshelf of cover art) and find the DZGUI app.
|
||||||
|
|
||||||
|
[start=7]
|
||||||
|
7. Right-click its cover and select **Manage** > **Set custom artwork**.
|
||||||
|
|
||||||
|
image::https://github.com/aclist/dztui/raw/testing/images/tutorial/06.png[06,700]
|
||||||
|
|
||||||
|
[start=8]
|
||||||
|
8. Navigate to the same path and select `grid.png`. The final result:
|
||||||
|
|
||||||
|
image::https://github.com/aclist/dztui/raw/testing/images/tutorial/07.png[07,700]
|
||||||
|
|
||||||
|
|
||||||
|
=== Updating the app
|
||||||
|
If DZGUI detects a new upstream version, it will prompt you to download it automatically. It backs up the original version before fetching the new one, then updates your config file with your existing values. Once finished, it will ask you to relaunch the app.
|
||||||
|
|
||||||
|
If you decline to upgrade to the new version, DZGUI will continue to the main menu with the current version.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
New versions may include changes to bugs that could prevent you from playing on certain servers. Upgrading is always advised.
|
||||||
|
|
||||||
|
If you experience a problem or need to restore the prior version of DZGUI and/or your configs, it is enough to simply replace the new version with the old one and relaunch the app. The files can be found at:
|
||||||
|
|
||||||
|
Script:
|
||||||
|
```
|
||||||
|
<path to script><script name>.old
|
||||||
|
```
|
||||||
|
E.g., if DZGUI is named `dzgui`, in the path `$HOME/bin`, it will be located at
|
||||||
|
```
|
||||||
|
$HOME/bin/dzgui.old
|
||||||
|
```
|
||||||
|
If launching DZGUI via its system shortcut, the backup file (similarly for log files) will be located under:
|
||||||
|
|
||||||
|
```
|
||||||
|
$HOME/.local/share/dzgui
|
||||||
|
```
|
||||||
|
|
||||||
|
Backup config files:
|
||||||
|
```
|
||||||
|
$HOME/.config/dztui/dztuirc.old
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
== Usage
|
||||||
|
Select <<Launch server list>> to fetch details for the server IDs you provided. Select the server you wish to connect to and click OK.
|
||||||
|
|
||||||
|
DZGUI will check the server's modset against your local mods. If you are missing any, it will prompt you to download them through the Steam Workshop and open a window in the background in the system browser.
|
||||||
|
|
||||||
|
Open each link and click Subscribe to schedule these for download.
|
||||||
|
[NOTE]
|
||||||
|
You must be logged into Steam for mod change to take effect. It can take some time for the subscribed mods to download and update. You can continue clicking Next to regenerate the list, or wait for all of them to complete.
|
||||||
|
|
||||||
|
Once all of the mods are downloaded and staged, DZGUI will notify you that it is ready to connect. The app hands the launch parameters to Steam and exits.
|
||||||
|
|
||||||
|
== Menu options
|
||||||
|
|
||||||
|
==== Launch server list
|
||||||
|
Fetches detailed server information on the list of servers saved in the config file. This is the main place you interact with DZGUI when choosing a server from your list. These details are:
|
||||||
|
|
||||||
|
- **Server**: name of the server, truncated to 50 chars
|
||||||
|
- **IP/port**: IP address and port in the format `ip:port`
|
||||||
|
- **Players**: online players, in the format `current/max`
|
||||||
|
- **Gametime**: in-game time on the 24-hour clock
|
||||||
|
- **Status**: whether the server is online or not
|
||||||
|
- **ID**: numerical ID from BattleMetrics, used as a reference when troubleshooting or sharing servers
|
||||||
|
- **Ping**: round-trip response time from the server
|
||||||
|
|
||||||
|
==== Quick connect to favorite server
|
||||||
|
Bypasses the server list and quick-connects to a single favorite server specified in advance using the <<Add favorite server>> option.
|
||||||
|
|
||||||
|
==== Add server by ID
|
||||||
|
Prompts you to add servers to the config file by ID. An indefinite number of servers can be added. These will be listed when using the <<Launch server list>> option.
|
||||||
|
|
||||||
|
==== Add favorite server
|
||||||
|
Prompts you to add/change a favorite server to the config file by ID. The name of the server will be updated in the header of the app. This server is used when selecting the <<Quick connect to favorite server>> option. If a favorite server is already enabled, this option switches to "Change favorite server."
|
||||||
|
|
||||||
|
==== Delete server
|
||||||
|
Prints a list of human-readable servers currently saved, and lets you delete them by selecting one from the list.
|
||||||
|
|
||||||
|
==== List installed mods
|
||||||
|
Prints a scrollable dialog containing all locally-installed mods and their corresponding symlinks IDs.
|
||||||
|
|
||||||
|
==== Toggle debug mode
|
||||||
|
Toggles debug mode, which is used to perform dry-runs and output what parameters would have been used to connect to a server. Enabling debug mode also exposes the <<Debug options>> menu, which contains some settings for advanced use.
|
||||||
|
|
||||||
|
==== Report bug
|
||||||
|
Using the system browser, opens the project's GitHub issues page to submit a report.
|
||||||
|
|
||||||
|
==== Help file
|
||||||
|
Using the system browser, opens this document.
|
||||||
|
|
||||||
|
==== View changelog
|
||||||
|
Prints the entire changelog up to the current version (and unreleased changes) in-app.
|
||||||
|
|
||||||
|
==== Debug options
|
||||||
|
If enabled, this menu contains a sub-menu with various advanced features, enumerated below.
|
||||||
|
|
||||||
|
===== Toggle branch
|
||||||
|
Used to toggle the branch to fetch DZGUI from between `stable` and `testing`. The app ships with the stable branch enabled, with the testing branch being used to elaborate various experimental features.
|
||||||
|
|
||||||
|
== Config file key/value pairs
|
||||||
|
Under normal usage, these values are populated and toggled automatically in-app. This config file is partially compatible DZTUI.
|
||||||
|
|
||||||
|
[%autowidth]
|
||||||
|
|===
|
||||||
|
|key|value
|
||||||
|
|
||||||
|
|`api_key`|the API key generated at BattleMetrics. See <<Setup>>
|
||||||
|
|`whitelist`|comma-separated list of server IDs from BattleMetrics; integer-values only
|
||||||
|
|`fav`|server to display in the `Fav` field and to quick-connect to (must be one only); integer-values only
|
||||||
|
|`name`|an arbitrary "handle" name used to identify the player on a server (required by some servers)
|
||||||
|
|`debug`|by default, set to 0; set to `1` to print launch options that would have been run, instead of actually connecting (used for troubleshooting and submitting bug reports)
|
||||||
|
|`branch`|by default, set to `stable`; set to `testing` to fetch the testing branch
|
||||||
|
|`seen_news`|stores a hash of the news item last seen by the client. This is used to suppress news messages until a new one is posted.
|
||||||
|
|===
|
||||||
|
|
||||||
|
== Troubleshooting/FAQ
|
||||||
|
|
||||||
|
.Mods take a long time to synchronize when subscribing from Workshop
|
||||||
|
Steam schedules the downloads in the background and processes them as they are subscribed to. This process is not instantaneous and can take some time. Check the **Downloads** pane of Steam to see live progress.
|
||||||
|
|
||||||
|
.Game does not launch through Steam
|
||||||
|
Check the logs emitted by Steam in the terminal, or in `<steam path>/error.log`.
|
||||||
|
|
||||||
|
.Game launches, but throws a "mod missing/check PBO file" error when connecting
|
||||||
|
You are missing mods or mods did not download correctly. Re-run the app to verify and link missing mods.
|
||||||
|
|
||||||
|
.Game and server launches, but when joining the game world, an error occurs
|
||||||
|
A mod is corrupted or the issue lies with the server. Replace the mods in question and reconnect.
|
||||||
|
|
||||||
|
== Testers wanted
|
||||||
|
If any of the below apply to you, your https://github.com/aclist/dztui/issues[reports] are encouraged:
|
||||||
|
|
||||||
|
- Using a high resolution (4K) monitor
|
||||||
|
- Own a Steam Deck
|
||||||
|
- Seeking DZTUI functionality in DZGUI, or vice versa
|
||||||
|
- Playing on a server with an enormous amount of mods
|
||||||
|
- Playing on a server with non-English mod names (?)
|
||||||
@@ -1,324 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -eo pipefail
|
|
||||||
version=0.3.0
|
|
||||||
release_url="https://raw.githubusercontent.com/aclist/dztui/main/dztui.sh"
|
|
||||||
aid=221100
|
|
||||||
game="dayz"
|
|
||||||
workshop="https://steamcommunity.com/sharedfiles/filedetails/?id="
|
|
||||||
api="https://api.battlemetrics.com/servers"
|
|
||||||
|
|
||||||
#BEGIN CONFIG================
|
|
||||||
steam_path="/path/to/steam"
|
|
||||||
workshop_dir="$steam_path/steamapps/workshop/content/$aid"
|
|
||||||
game_dir="$steam_path/steamapps/common/DayZ"
|
|
||||||
key="APIKEY"
|
|
||||||
whitelist="8039514,8789747,4363928,8199330,11359652,12862329"
|
|
||||||
fav="8789747"
|
|
||||||
name="player"
|
|
||||||
separator="│"
|
|
||||||
ping=1
|
|
||||||
debug=0
|
|
||||||
#END CONFIG================
|
|
||||||
|
|
||||||
#STEAMCMD CONFIG===========
|
|
||||||
auto_install_mods=0
|
|
||||||
steamcmd_user="steam"
|
|
||||||
steam_username="STEAMUSER"
|
|
||||||
staging_dir="/tmp"
|
|
||||||
#END STEAMCMD CONFIG=======
|
|
||||||
|
|
||||||
declare -A deps
|
|
||||||
deps=([awk]="5.1.1" [curl]="7.80.0" [jq]="1.6" [column]="2.37.2" [tr]="9.0" [comm]="9.0")
|
|
||||||
max_range=$(awk -F, '{print NF}' <<< $whitelist)
|
|
||||||
|
|
||||||
err(){
|
|
||||||
printf "[ERROR] %s\n" "$1"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
version_check(){
|
|
||||||
upstream=$(curl -Ls "$release_url" | awk -F= 'NR==3 {print $2}')
|
|
||||||
printf "[INFO] Checking for new version\n"
|
|
||||||
if [[ ! $upstream == "$version" ]]; then
|
|
||||||
printf "[INFO] A newer version of DZTUI is available at:\n$release_url.\n"
|
|
||||||
while true; do
|
|
||||||
read -p "Continue anyway? [Y/n] " response
|
|
||||||
if [[ $response == "Y" ]]; then
|
|
||||||
break
|
|
||||||
elif [[ $response == "n" ]]; then
|
|
||||||
exit_msg
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
depcheck(){
|
|
||||||
for dep in "${!deps[@]}"; do
|
|
||||||
command -v $dep 2>&1>/dev/null || (printf "[ERROR] Requires %s >= %s\n" $dep ${deps[$dep]} ; exit 1)
|
|
||||||
done
|
|
||||||
}
|
|
||||||
column_check(){
|
|
||||||
echo foo | column -o$'\t' &>/dev/null || err "column version >= 2.37.2 required"
|
|
||||||
}
|
|
||||||
varcheck(){
|
|
||||||
[[ -z $key ]] && (err "Missing API key")
|
|
||||||
[[ -z $whitelist ]] && (err "Missing server IDs")
|
|
||||||
[[ ! -d $workshop_dir ]] && (err "Malformed workshop path")
|
|
||||||
[[ ! -d $game_dir ]] && (err "Malformed game path")
|
|
||||||
[[ $whitelist =~ [[:space:]] ]] && (err "Separate whitelist values with commas")
|
|
||||||
IFS=,
|
|
||||||
[[ ! "${whitelist[*]}" =~ "${fav}" ]] && (err "Fav key value not in whitelist")
|
|
||||||
unset IFS
|
|
||||||
}
|
|
||||||
checks() {
|
|
||||||
depcheck
|
|
||||||
column_check
|
|
||||||
version_check
|
|
||||||
varcheck
|
|
||||||
}
|
|
||||||
check_ping(){
|
|
||||||
if [[ $ping -eq 1 ]]; then
|
|
||||||
ping_ip=$(echo -e "$i" | awk -F'\t' '{print $2}' | awk -F: '{print $1}')
|
|
||||||
ms=$(ping -c 1 "$ping_ip" | awk -Ftime= '/time=/ {print $2}')
|
|
||||||
[[ -z $ms ]] && ms="Timeout" || :
|
|
||||||
printf "%s\t%s\n" "$i" "$ms"
|
|
||||||
else
|
|
||||||
printf "%s\n" "$i"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
parse_json(){
|
|
||||||
list=$(jq -r '.data[] .attributes | "\(.name)\t\(.ip):\(.port)\t\(.players)/\(.maxPlayers)\t\(.status)\t\(.id)"')
|
|
||||||
readarray -t list <<< $list
|
|
||||||
for i in "${list[@]}"; do
|
|
||||||
check_ping
|
|
||||||
done
|
|
||||||
}
|
|
||||||
symlinks(){
|
|
||||||
for d in "$workshop_dir"/*; do
|
|
||||||
id=$(awk -F"= " '/publishedid/ {print $2}' "$d"/meta.cpp | awk -F\; '{print $1}')
|
|
||||||
mod=$(awk -F\" '/name/ {print $2}' "$d"/meta.cpp | sed -E 's/[^[:alpha:]0-9]+/_/g; s/^_|_$//g')
|
|
||||||
link="@$id-$mod"
|
|
||||||
[[ -h "$game_dir/$link" ]] && : ||
|
|
||||||
printf "[INFO] Creating symlink for $mod\n"
|
|
||||||
ln -fs "$d" "$game_dir/$link"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
installed_mods(){
|
|
||||||
ls -1 "$workshop_dir"
|
|
||||||
}
|
|
||||||
|
|
||||||
list_mods(){
|
|
||||||
printf "Installed mods: "
|
|
||||||
for d in $(installed_mods); do
|
|
||||||
awk -F\" '/name/ {print $2}' "$workshop_dir"/$d/meta.cpp
|
|
||||||
done | sort | awk 'NR > 1 { printf(", ") } {printf("%s",$0)}'
|
|
||||||
printf "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
columnize(){
|
|
||||||
column -t -s$'\t' -o$" $separator "
|
|
||||||
}
|
|
||||||
test_fav(){
|
|
||||||
if [[ -n $fav ]]; then
|
|
||||||
if [[ $(echo -e "${tabled[$i]}" | awk -F'\t' -v fav=$fav '$5 == fav') ]] ; then
|
|
||||||
printf "%s│▶%s\n" "$i" "${tabled[$i]}"
|
|
||||||
else
|
|
||||||
printf "%s│ %s\n" "$i" "${tabled[$i]}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
printf "%s│ %s\n" "$i" "${tabled[$i]}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
table(){
|
|
||||||
range=$((${#tabled[@]} - 1))
|
|
||||||
for ((i=0;i<="$range";i++)); do
|
|
||||||
test_fav
|
|
||||||
done
|
|
||||||
}
|
|
||||||
concat_mods(){
|
|
||||||
readarray -t serv <<< "$remote_mods"
|
|
||||||
for i in "${serv[@]}"; do
|
|
||||||
id=$(awk -F"= " '/publishedid/ {print $2}' "$workshop_dir"/$i/meta.cpp | awk -F\; '{print $1}')
|
|
||||||
mod=$(awk -F\" '/name/ {print $2}' "$workshop_dir"/$i/meta.cpp | sed -E 's/[^[:alpha:]0-9]+/_/g; s/^_|_$//g')
|
|
||||||
link="@$id-$mod;"
|
|
||||||
echo -e "$link"
|
|
||||||
done | tr -d '\n' | perl -ple 'chop'
|
|
||||||
}
|
|
||||||
launch(){
|
|
||||||
mods=$(concat_mods)
|
|
||||||
ip=$(echo -e "${tabled[$sel]}" | awk -F'\t' '{print $2}')
|
|
||||||
printf "[INFO] Connecting to: $connecting_to\n"
|
|
||||||
if [[ $debug -eq 1 ]]; then
|
|
||||||
printf "[DEBUG] steam -applaunch $aid -connect=$ip -nolauncher -nosplash -skipintro \"-mod=$mods\"\n"
|
|
||||||
else
|
|
||||||
steam -applaunch $aid -connect=$ip -nolauncher -nosplash -skipintro -name=$name \"-mod=$mods\"
|
|
||||||
printf "Good luck out there. DZTUI $version\n"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
launch_fav(){
|
|
||||||
if [[ -n $fav ]]; then
|
|
||||||
sorted_id=$fav
|
|
||||||
sel=$(table | awk -F'\t' -v fav=$fav '$5 == fav {print substr($1,1,1)}')
|
|
||||||
connect
|
|
||||||
else
|
|
||||||
printf "[INFO] No favorite set\n"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
manual_mod_install(){
|
|
||||||
printf "[ERROR] Missing mods. Open these links and subscribe to each one, then reconnect\n"
|
|
||||||
for i in $diff; do
|
|
||||||
printf "%s%s\n" "$workshop" $i
|
|
||||||
done
|
|
||||||
}
|
|
||||||
steamcmd_modlist(){
|
|
||||||
for i in $diff; do
|
|
||||||
printf "+workshop_download_item %s %s " $aid $i
|
|
||||||
done
|
|
||||||
}
|
|
||||||
move_files(){
|
|
||||||
sudo chown -R $USER:$gid "$staging_dir"/steamapps
|
|
||||||
cp -R "$staging_dir"/steamapps/workshop/content/$aid/* "$workshop_dir"
|
|
||||||
rm -r "$staging_dir"/steamapps
|
|
||||||
}
|
|
||||||
auto_mod_download(){
|
|
||||||
sudo su -c "steamcmd +force_install_dir $staging_dir +login $steam_username $(steamcmd_modlist) +quit" $steamcmd_user
|
|
||||||
[[ "$(ls -A $staging_dir/steamapps)" ]] && move_files || return 1
|
|
||||||
}
|
|
||||||
auto_mod_install(){
|
|
||||||
printf "[ERROR] Missing mods. Invoking steamcmd for user $steamcmd_user\n"
|
|
||||||
if [[ -z $steamcmd_user ]]; then
|
|
||||||
err "steamcmd user value was empty. Reverting to manual mode"
|
|
||||||
elif
|
|
||||||
id $steamcmd_user &>/dev/null
|
|
||||||
[[ $? -eq 1 ]]; then
|
|
||||||
err "Invalid steamcmd user. Reverting to manual mode"
|
|
||||||
elif
|
|
||||||
command -v steamcmd &>/dev/null
|
|
||||||
[[ $? -eq 1 ]]; then
|
|
||||||
err "steamcmd not installed. See: https://developer.valvesoftware.com/wiki/SteamCMD"
|
|
||||||
else
|
|
||||||
printf "[INFO] Found steamcmd user. Downloading mods\n"
|
|
||||||
revert_msg="Something went wrong. Reverting to manual mode"
|
|
||||||
auto_mod_download
|
|
||||||
[[ $? -eq 0 ]] && printf "\n"; init_table || err "$revert_msg"
|
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
|
||||||
failed_mod_check(){
|
|
||||||
[[ $auto_install_mods -eq 1 ]] && auto_mod_install || manual_mod_install
|
|
||||||
}
|
|
||||||
passed_mod_check(){
|
|
||||||
printf "[INFO] Mod check passed\n"
|
|
||||||
connecting_to=$(echo -e "${tabled[$sel]}" | awk -F'\t' '{print $1,$2}')
|
|
||||||
symlinks
|
|
||||||
launch
|
|
||||||
|
|
||||||
}
|
|
||||||
check_workshop(){
|
|
||||||
curl -Ls "$url${modlist[$i]}" | grep data-appid | awk -F\" '{print $8}'
|
|
||||||
}
|
|
||||||
validate_mods(){
|
|
||||||
url="https://steamcommunity.com/sharedfiles/filedetails/?id="
|
|
||||||
aid=221100
|
|
||||||
tput civis
|
|
||||||
newlist=()
|
|
||||||
readarray -t modlist <<< $remote_mods
|
|
||||||
for ((i=0;i<=${#modlist[@]};i++)); do
|
|
||||||
printf "[INFO] Verifying integrity of server modlist manifest [$i/${#modlist[@]}]\r"
|
|
||||||
[[ $(check_workshop) -eq $aid ]] && newlist+=("${modlist[$i]}") || :
|
|
||||||
sleep 2s
|
|
||||||
done
|
|
||||||
tput cnorm
|
|
||||||
printf "\n"
|
|
||||||
}
|
|
||||||
server_modlist(){
|
|
||||||
for i in "${newlist[@]}"; do
|
|
||||||
printf "$i\n"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
compare(){
|
|
||||||
fetch_mods
|
|
||||||
validate_mods
|
|
||||||
diff=$(comm -23 <(server_modlist | sort) <(installed_mods | sort))
|
|
||||||
}
|
|
||||||
connect(){
|
|
||||||
compare
|
|
||||||
if [[ -n $diff ]]; then
|
|
||||||
failed_mod_check
|
|
||||||
else
|
|
||||||
passed_mod_check
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
fetch_mods(){
|
|
||||||
remote_mods=$(curl -s "$api" -H "Authorization: Bearer "$key"" -G -d filter[ids][whitelist]="$sorted_id" -d "sort=-players" \
|
|
||||||
| jq -r '.data[] .attributes .details .modIds[]')
|
|
||||||
}
|
|
||||||
query_api(){
|
|
||||||
response=$(curl -s "$api" -H "Authorization: Bearer "$key"" -G -d "sort=-players" \
|
|
||||||
-d "filter[game]=$game" -d "filter[ids][whitelist]=$whitelist")
|
|
||||||
if [[ "$(jq -r 'keys[]' <<< $response)" == "errors" ]]; then
|
|
||||||
printf "[ERROR] %s: check API key\n" "$(jq -r '.errors[] .status' <<< $response)"
|
|
||||||
return 1
|
|
||||||
elif
|
|
||||||
[[ -z "$(jq -r '.data[]' <<< $response)" ]]; then
|
|
||||||
printf "[ERROR] Check server ID\n"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
init_table(){
|
|
||||||
tput civis
|
|
||||||
printf "[INFO] Polling servers. Please wait.\r"
|
|
||||||
query_api
|
|
||||||
readarray -t tabled <<< $(parse_json <<< $response)
|
|
||||||
tput cnorm
|
|
||||||
tput cuu1
|
|
||||||
tput el
|
|
||||||
table | columnize
|
|
||||||
}
|
|
||||||
get_sorted_id(){
|
|
||||||
sorted_id=$(echo -e "${tabled[$sel]}" | awk -F'\t' '{print $5}')
|
|
||||||
}
|
|
||||||
menu(){
|
|
||||||
printf "\n"
|
|
||||||
printf "f$separator Launch favorite\n"
|
|
||||||
printf "l$separator List installed mods\n"
|
|
||||||
printf "r$separator Refresh\n"
|
|
||||||
printf "q$separator Quit\n"
|
|
||||||
printf "\n"
|
|
||||||
}
|
|
||||||
exit_msg(){
|
|
||||||
printf "DZTUI $version\n"
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
forced_exit(){
|
|
||||||
tput cnorm
|
|
||||||
printf "\n"
|
|
||||||
exit_msg
|
|
||||||
}
|
|
||||||
main(){
|
|
||||||
checks
|
|
||||||
init_table
|
|
||||||
while true; do
|
|
||||||
menu
|
|
||||||
read -p "Selection: " sel
|
|
||||||
if [[ $sel =~ ^[0-9]+$ ]]; then
|
|
||||||
if [[ $sel -gt $max_range ]]; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
get_sorted_id
|
|
||||||
connect
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
case $sel in
|
|
||||||
r) init_table ;;
|
|
||||||
f) launch_fav ;;
|
|
||||||
l) list_mods ;;
|
|
||||||
q) exit_msg ;;
|
|
||||||
*) : ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
trap forced_exit INT
|
|
||||||
main
|
|
||||||
|
Before Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 497 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 81 B |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 609 KiB |
|
After Width: | Height: | Size: 569 KiB |
|
After Width: | Height: | Size: 417 KiB |
|
After Width: | Height: | Size: 223 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
curl "https://raw.githubusercontent.com/aclist/dztui/dzgui/dzgui.sh" > dzgui.sh
|
||||||
|
chmod +x dzgui.sh
|
||||||
|
./dzgui.sh
|
||||||