Compare commits
127 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
64f4ae6429 | ||
|
b2cc21aed0 | ||
|
dc5957ea41 | ||
|
54abce4d30 | ||
|
6ae33cdcb3 | ||
|
c9d30fa95a | ||
|
dc81430f6b | ||
|
9c122506ce | ||
|
f2ba92c31d | ||
|
c92fb88e83 | ||
|
1e0e0090f5 | ||
|
48f6a96a01 | ||
|
f4fe1c6699 | ||
|
59f1b09337 | ||
|
237fa8c16f | ||
|
78e155408e | ||
|
3033dd2315 | ||
|
48851fa8d3 | ||
|
84ea4e48af | ||
|
b408f13cce | ||
|
959c3a8a61 | ||
|
73df20ebb6 | ||
|
08814a8c3e | ||
|
65094d4701 | ||
|
a20b1acdda | ||
|
75b1d6254b | ||
|
65f05a5a1c | ||
|
fa6bdc9f29 | ||
|
7595a46b44 | ||
|
c41a843315 | ||
|
a90a60ec3a | ||
|
209b599120 | ||
|
9f00b0c0e7 | ||
|
aaede9b6cb | ||
|
8a14008706 | ||
|
ad7e78ec47 | ||
|
140f4c335f | ||
|
3e1a266c3e | ||
|
92663425ef | ||
|
ffa379e6dd | ||
|
a41375a791 | ||
|
ac76e9bb89 | ||
|
546d8c4cdf | ||
|
12ccc9554f | ||
|
c117eaeb31 | ||
|
50c7b9fbd7 | ||
|
f09271c29c | ||
|
b71c15cb8e | ||
|
a3000bd2fa | ||
|
cc00cad4f2 | ||
|
6a16299cee | ||
|
565a69566c | ||
|
1727446cfc | ||
|
4282eb7b75 | ||
|
a2922540c5 | ||
|
601abd008f | ||
|
322fd2f98a | ||
|
e061bca7a3 | ||
|
87e86cc954 | ||
|
d5d847df75 | ||
|
d620bc9838 | ||
|
76a7d8b2c6 | ||
|
6c7fbd1ff1 | ||
|
18651a68ca | ||
|
79559fe46a | ||
|
8fd66d16af | ||
|
4d3c6b9dab | ||
|
7ca7615222 | ||
|
2195f42abc | ||
|
f7635d4089 | ||
|
9598ec3dfe | ||
|
37266207e7 | ||
|
e041df80c5 | ||
|
b157bcb2c2 | ||
|
beae0adce5 | ||
|
f9ec044a15 | ||
|
0be3adf8d1 | ||
|
59f347462d | ||
|
78e4e18176 | ||
|
e0f4a5102e | ||
|
c80765d091 | ||
|
3b77755848 | ||
|
4c1114f3e0 | ||
|
b69611e66b | ||
|
6ec4deed32 | ||
|
744e309190 | ||
|
83e1f67d0d | ||
|
b83720af0a | ||
|
7e36b7496c | ||
|
98cbc2a9a7 | ||
|
85e17260eb | ||
|
14181845fb | ||
|
9323f12442 | ||
|
a7bf44f105 | ||
|
e715cd5abf | ||
|
a234232751 | ||
|
e84a8db0aa | ||
|
fdf35efa81 | ||
|
e94d71b80e | ||
|
d233dfb53c | ||
|
d04083c473 | ||
|
98d43d2627 | ||
|
4fe5ed1f77 | ||
|
7398ca6ca7 | ||
|
4e6ef5d0e5 | ||
|
33463f1a6e | ||
|
41311ed5ad | ||
|
69686b3a09 | ||
|
8be94a31ac | ||
|
99da9832ff | ||
|
b175fc2b5f | ||
|
02ae0459cb | ||
|
611049ec1b | ||
|
2e4467779d | ||
|
e2c22a716b | ||
|
796c67d708 | ||
|
21b7b1ea4b | ||
|
c4046ae148 | ||
|
b1decd0b17 | ||
|
966a63df62 | ||
|
abb583aeff | ||
|
06584a3195 | ||
|
7fcfa2aa57 | ||
|
2e4436ed9a | ||
|
d92319e15f | ||
|
a5cb68e7fa | ||
|
eb161c2375 |
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@ -3,4 +3,4 @@ updates:
|
|||||||
- package-ecosystem: "cargo" # See documentation for possible values
|
- package-ecosystem: "cargo" # See documentation for possible values
|
||||||
directory: "/" # Location of package manifests
|
directory: "/" # Location of package manifests
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "weekly"
|
||||||
|
17
.github/workflows/release.yml
vendored
17
.github/workflows/release.yml
vendored
@ -11,15 +11,22 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: taiki-e/create-gh-release-action@v1
|
- uses: taiki-e/create-gh-release-action@v1
|
||||||
env:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
draft: true
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
upload-assets:
|
upload-assets:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os:
|
include:
|
||||||
- ubuntu-20.04
|
- target: x86_64-unknown-linux-gnu
|
||||||
- windows-latest
|
os: ubuntu-20.04
|
||||||
|
- target: i686-unknown-linux-gnu
|
||||||
|
os: ubuntu-20.04
|
||||||
|
- target: x86_64-pc-windows-msvc
|
||||||
|
os: windows-latest
|
||||||
|
- target: i686-pc-windows-msvc
|
||||||
|
os: windows-latest
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
797
Cargo.lock
generated
797
Cargo.lock
generated
@ -3,15 +3,47 @@
|
|||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alterware-launcher"
|
name = "adler"
|
||||||
version = "0.2.2"
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alterware-launcher"
|
||||||
|
version = "0.5.2"
|
||||||
|
dependencies = [
|
||||||
|
"colored",
|
||||||
"http_req",
|
"http_req",
|
||||||
|
"mslnk",
|
||||||
"rand",
|
"rand",
|
||||||
|
"self-replace",
|
||||||
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1_smol",
|
"sha1_smol",
|
||||||
|
"steamlocate",
|
||||||
"winres",
|
"winres",
|
||||||
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -20,17 +52,74 @@ version = "0.13.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64ct"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.13.0"
|
version = "3.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bzip2"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
|
||||||
|
dependencies = [
|
||||||
|
"bzip2-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bzip2-sys"
|
||||||
|
version = "0.1.11+1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.79"
|
version = "1.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||||
|
dependencies = [
|
||||||
|
"jobserver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@ -38,6 +127,163 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colored"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6"
|
||||||
|
dependencies = [
|
||||||
|
"is-terminal",
|
||||||
|
"lazy_static",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deranged"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "3.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||||
|
dependencies = [
|
||||||
|
"errno-dragonfly",
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno-dragonfly"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
@ -50,10 +296,25 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http_req"
|
name = "hermit-abi"
|
||||||
version = "0.9.1"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5825a38a94c3aff23ea7f60572726829ef055ca02fc64899c3e2e7db2ce4f03f"
|
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http_req"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42ce34c74ec562d68f2c23a532c62c1332ff1d1b6147fd118bd1938e090137d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls",
|
"rustls",
|
||||||
"unicase",
|
"unicase",
|
||||||
@ -61,12 +322,50 @@ dependencies = [
|
|||||||
"webpki-roots",
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.63"
|
version = "0.3.63"
|
||||||
@ -77,10 +376,47 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "keyvalues-parser"
|
||||||
version = "0.2.144"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
|
checksum = "7d990301996c856ea07a84bc291e76f1273db52683663efc05c8d355976897e5"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_derive",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "keyvalues-serde"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da419ac133bb3ddf0dbf9c12fcc0ce01d994fcb65f6f1713faf15cc689320b5f"
|
||||||
|
dependencies = [
|
||||||
|
"keyvalues-parser",
|
||||||
|
"once_cell",
|
||||||
|
"paste",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.147"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
@ -88,12 +424,117 @@ version = "0.4.18"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
|
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mslnk"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86c97310150b7f496a93f31690da7822b99d95ff68ca9d30fb09d3ad54375c76"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"byteorder",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.17.2"
|
version = "1.17.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
|
checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "password-hash"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"rand_core",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pbkdf2"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"hmac",
|
||||||
|
"password-hash",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest"
|
||||||
|
version = "2.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
"ucd-trie",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_derive"
|
||||||
|
version = "2.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "666d00490d4ac815001da55838c500eafb0320019bbaa44444137c48b443a853"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_generator",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_generator"
|
||||||
|
version = "2.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_meta",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_meta"
|
||||||
|
version = "2.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"pest",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@ -102,9 +543,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.59"
|
version = "1.0.63"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
|
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@ -148,6 +589,64 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"redox_syscall 0.2.16",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.16.20"
|
version = "0.16.20"
|
||||||
@ -163,6 +662,19 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.0",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.19.1"
|
version = "0.19.1"
|
||||||
@ -193,19 +705,36 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "self-replace"
|
||||||
version = "1.0.164"
|
version = "1.3.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
|
checksum = "525db198616b2bcd0f245daf7bfd8130222f7ee6af9ff9984c19a61bf1160c55"
|
||||||
|
dependencies = [
|
||||||
|
"fastrand 1.9.0",
|
||||||
|
"tempfile",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.188"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.164"
|
version = "1.0.188"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
|
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -214,21 +743,43 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.96"
|
version = "1.0.107"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
|
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1_smol"
|
name = "sha1_smol"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@ -236,16 +787,85 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "steamlocate"
|
||||||
version = "2.0.18"
|
version = "2.0.0-alpha.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
|
checksum = "2b1568c4a70a26c4373fe1131ffa4eff055459631b6e40c6bc118615f2d870c3"
|
||||||
|
dependencies = [
|
||||||
|
"dirs",
|
||||||
|
"keyvalues-parser",
|
||||||
|
"keyvalues-serde",
|
||||||
|
"serde",
|
||||||
|
"winreg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"fastrand 2.0.0",
|
||||||
|
"redox_syscall 0.3.5",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48"
|
||||||
|
dependencies = [
|
||||||
|
"deranged",
|
||||||
|
"serde",
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
@ -255,6 +875,18 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucd-trie"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
@ -393,6 +1025,81 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winreg"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winres"
|
name = "winres"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
@ -401,3 +1108,53 @@ checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zip"
|
||||||
|
version = "0.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
|
||||||
|
dependencies = [
|
||||||
|
"aes",
|
||||||
|
"byteorder",
|
||||||
|
"bzip2",
|
||||||
|
"constant_time_eq",
|
||||||
|
"crc32fast",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"flate2",
|
||||||
|
"hmac",
|
||||||
|
"pbkdf2",
|
||||||
|
"sha1",
|
||||||
|
"time",
|
||||||
|
"zstd",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd"
|
||||||
|
version = "0.11.2+zstd.1.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-safe",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-safe"
|
||||||
|
version = "5.0.2+zstd.1.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"zstd-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-sys"
|
||||||
|
version = "2.0.8+zstd.1.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
22
Cargo.toml
22
Cargo.toml
@ -1,28 +1,40 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "alterware-launcher"
|
name = "alterware-launcher"
|
||||||
version = "0.2.3"
|
version = "0.5.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
build = "res/build.rs"
|
build = "res/build.rs"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
|
|
||||||
|
# Symbols are a nice thing
|
||||||
|
debug = true
|
||||||
|
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
http_req = { version = "0.9.0", default-features = false, features = [
|
http_req = { version = "0.9.3", default-features = false, features = [
|
||||||
"rust-tls",
|
"rust-tls",
|
||||||
] }
|
] }
|
||||||
sha1_smol = "1.0.0"
|
sha1_smol = "1.0.0"
|
||||||
serde = { version = "1.0.164", features = ["derive"] }
|
serde = { version = "1.0.188", features = ["derive"] }
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.107"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
semver = "1.0.19"
|
||||||
|
zip = "0.6.6"
|
||||||
|
colored = "2.0.4"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
steamlocate = "2.0.0-alpha.0"
|
||||||
|
mslnk = "0.1.8"
|
||||||
|
self-replace = "1.3.7"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
winres = "0.1.12"
|
winres = "0.1.12"
|
||||||
|
|
||||||
[package.metadata.winres]
|
[package.metadata.winres]
|
||||||
OriginalFilename = "alterware-launcher.exe"
|
OriginalFilename = "alterware-launcher.exe"
|
||||||
FileDescription = "AlterWare mod updater & launcher"
|
FileDescription = "AlterWare Launcher"
|
||||||
ProductName = "AlterWare Launcher"
|
ProductName = "AlterWare Launcher"
|
69
README.md
69
README.md
@ -1,10 +1,69 @@
|
|||||||
# alterware-launcher
|
# AlterWare Launcher
|
||||||
|
|
||||||
1. Download [latest release](https://github.com/mxve/alterware-launcher/releases/latest/download/alterware-launcher-x86_64-pc-windows-msvc.zip)
|
### [AlterWare.dev](https://alterware.dev)
|
||||||
2. Unpack the archive and place alterware-launcher.exe in the game directory
|
|
||||||
|
##### IW4x | IW4-SP | IW5-Mod | IW6-Mod | S1-Mod
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Installation
|
||||||
|
|
||||||
|
1. Download the [latest alterware-launcher.exe](https://github.com/mxve/alterware-launcher/releases/latest/download/alterware-launcher.exe)
|
||||||
|
2. Place alterware-launcher.exe in the game directory
|
||||||
3. Run alterware-launcher.exe, after updating the game will launch automatically
|
3. Run alterware-launcher.exe, after updating the game will launch automatically
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
- Passing ```iw4-sp```, ```iw5-mod```, ```iw6-mod``` or ```s1-mod``` as the first argument will skip automatic game detection
|
#### Command line arguments
|
||||||
- Passing ```update``` will stop the launcher from launching the game
|
|
||||||
|
- ```iw4-sp```, ```iw4x```, ```iw5-mod```, ```iw6-mod```, ```s1-mod```
|
||||||
|
- Skip automatic detection and launch the specified game
|
||||||
|
- This should always be the first argument if used
|
||||||
|
- ```--update```, ```-u```
|
||||||
|
- Only update the game, don't launch it
|
||||||
|
- ```--skip-launcher-update```
|
||||||
|
- Don't update the launcher
|
||||||
|
- ```--bonus```
|
||||||
|
- Download bonus content
|
||||||
|
- ```--force```, ```-f```
|
||||||
|
- Force file hash recheck
|
||||||
|
- ```--path```, ```-p```
|
||||||
|
- Set the game path
|
||||||
|
- Do not include a trailing backslash in the path
|
||||||
|
- ```--pass```
|
||||||
|
- Pass additional arguments to the game
|
||||||
|
- ```--version```, ```-v```
|
||||||
|
- Print the launcher version
|
||||||
|
|
||||||
|
Example: ```alterware-launcher.exe iw4x --bonus -u --path "C:\Games\IW4x" --pass "-console"```
|
||||||
|
|
||||||
|
Some arguments can be set in alterware-launcher.json, args generally override the values of the config.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Support
|
||||||
|
|
||||||
|
Visit the [AlterWare Forum](https://forum.alterware.dev/) or [Discord](https://discord.gg/2ETE8engZM) for support.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Building from Source
|
||||||
|
|
||||||
|
- [Install Rust](https://rustup.rs/)
|
||||||
|
- Clone the repository
|
||||||
|
- Run ```cargo build --release```
|
||||||
|
- The executable will be located in ```target/release```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Note for server owners:
|
||||||
|
When the launcher updates itself it needs to be restarted. It will return exit code 201 in this case.
|
||||||
|
|
||||||
|
```
|
||||||
|
@echo off
|
||||||
|
:loop
|
||||||
|
start /wait alterware-launcher.exe --update
|
||||||
|
if %errorlevel% equ 201 (
|
||||||
|
goto loop
|
||||||
|
)
|
||||||
|
```
|
30
src/config.rs
Normal file
30
src/config.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use crate::structs::Config;
|
||||||
|
|
||||||
|
use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
|
pub fn load(config_path: PathBuf) -> Config {
|
||||||
|
if config_path.exists() {
|
||||||
|
let cfg = fs::read_to_string(&config_path).unwrap();
|
||||||
|
let cfg: Config = serde_json::from_str(&cfg).unwrap_or(Config::default());
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
save(config_path.clone(), Config::default());
|
||||||
|
Config::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(config_path: PathBuf, config: Config) {
|
||||||
|
fs::write(config_path, serde_json::to_string_pretty(&config).unwrap()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_value(config_path: PathBuf, key: &str, value: bool) {
|
||||||
|
let mut config = load(config_path.clone());
|
||||||
|
match key {
|
||||||
|
"update_only" => config.update_only = value,
|
||||||
|
"skip_self_update" => config.skip_self_update = value,
|
||||||
|
"download_bonus_content" => config.download_bonus_content = value,
|
||||||
|
"ask_bonus_content" => config.ask_bonus_content = value,
|
||||||
|
"force_update" => config.force_update = value,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
save(config_path, config);
|
||||||
|
}
|
22
src/github.rs
Normal file
22
src/github.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use semver::Version;
|
||||||
|
|
||||||
|
pub fn latest_tag(owner: &str, repo: &str) -> String {
|
||||||
|
let github_body = crate::http::get_body_string(
|
||||||
|
format!(
|
||||||
|
"https://api.github.com/repos/{}/{}/releases/latest",
|
||||||
|
owner, repo
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
|
let github_json: serde_json::Value = serde_json::from_str(&github_body).unwrap();
|
||||||
|
github_json["tag_name"].to_string().replace('"', "")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn latest_version(owner: &str, repo: &str) -> Version {
|
||||||
|
let tag = latest_tag(owner, repo).replace('v', "");
|
||||||
|
Version::parse(&tag).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn latest_release_url(owner: &str, repo: &str) -> String {
|
||||||
|
format!("https://github.com/{}/{}/releases/latest", owner, repo)
|
||||||
|
}
|
5
src/global.rs
Normal file
5
src/global.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
pub const MASTER: &str = "https://master.alterware.dev";
|
||||||
|
pub const GH_OWNER: &str = "mxve";
|
||||||
|
pub const GH_REPO: &str = "alterware-launcher";
|
||||||
|
pub const GH_IW4X_OWNER: &str = "iw4x";
|
||||||
|
pub const GH_IW4X_REPO: &str = "iw4x-client";
|
13
src/http.rs
13
src/http.rs
@ -2,10 +2,21 @@ use std::{fs, io::Write, path::Path, str};
|
|||||||
|
|
||||||
pub fn get_body(url: &str) -> Vec<u8> {
|
pub fn get_body(url: &str) -> Vec<u8> {
|
||||||
let mut res: Vec<u8> = Vec::new();
|
let mut res: Vec<u8> = Vec::new();
|
||||||
http_req::request::get(url, &mut res).unwrap_or_else(|error| {
|
let req = http_req::request::Request::new(&url.try_into().unwrap())
|
||||||
|
.header(
|
||||||
|
"User-Agent",
|
||||||
|
"AlterWare Launcher | github.com/mxve/alterware-launcher",
|
||||||
|
)
|
||||||
|
.send(&mut res)
|
||||||
|
.unwrap_or_else(|error| {
|
||||||
panic!("\n\n{}:\n{:?}", "Error", error);
|
panic!("\n\n{}:\n{:?}", "Error", error);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if req.status_code() == http_req::response::StatusCode::new(302) {
|
||||||
|
let location = req.headers().get("Location").unwrap().as_str();
|
||||||
|
return get_body(location);
|
||||||
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
src/io.rs
Normal file
22
src/io.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use std::{fs, path::Path};
|
||||||
|
|
||||||
|
pub fn unzip(zip_path: &Path, out_path: &Path) {
|
||||||
|
let mut archive = zip::ZipArchive::new(fs::File::open(zip_path).unwrap()).unwrap();
|
||||||
|
for i in 0..archive.len() {
|
||||||
|
let mut file = archive.by_index(i).unwrap();
|
||||||
|
let outpath = out_path.join(file.name());
|
||||||
|
|
||||||
|
if (*file.name()).ends_with('/') {
|
||||||
|
fs::create_dir_all(outpath).unwrap();
|
||||||
|
} else {
|
||||||
|
println!("Unpacking {}", file.name());
|
||||||
|
if let Some(p) = outpath.parent() {
|
||||||
|
if !p.exists() {
|
||||||
|
fs::create_dir_all(p).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut outfile = fs::File::create(&outpath).unwrap();
|
||||||
|
std::io::copy(&mut file, &mut outfile).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
src/iw4x.rs
Normal file
42
src/iw4x.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use crate::github;
|
||||||
|
use crate::global::*;
|
||||||
|
use crate::http;
|
||||||
|
use crate::misc;
|
||||||
|
|
||||||
|
use colored::*;
|
||||||
|
use std::{fs, path::Path};
|
||||||
|
|
||||||
|
pub fn local_revision(dir: &Path) -> u16 {
|
||||||
|
if let Ok(revision) = fs::read_to_string(dir.join(".iw4xrevision")) {
|
||||||
|
misc::rev_to_int(&revision)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remote_revision() -> u16 {
|
||||||
|
misc::rev_to_int(&github::latest_tag(GH_IW4X_OWNER, GH_IW4X_REPO))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(dir: &Path) {
|
||||||
|
let remote = remote_revision();
|
||||||
|
let local = local_revision(dir);
|
||||||
|
|
||||||
|
if remote <= local && dir.join("iw4x.dll").exists() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"[{}] {}",
|
||||||
|
"Downloading".bright_yellow(),
|
||||||
|
dir.join("iw4x.dll").display()
|
||||||
|
);
|
||||||
|
http::download_file(
|
||||||
|
&format!(
|
||||||
|
"{}/download/iw4x.dll",
|
||||||
|
github::latest_release_url(GH_IW4X_OWNER, GH_IW4X_REPO)
|
||||||
|
),
|
||||||
|
&dir.join("iw4x.dll"),
|
||||||
|
);
|
||||||
|
fs::write(dir.join(".iw4xrevision"), format!("r{}", remote)).unwrap();
|
||||||
|
}
|
493
src/main.rs
493
src/main.rs
@ -1,119 +1,424 @@
|
|||||||
|
mod config;
|
||||||
|
mod github;
|
||||||
|
mod global;
|
||||||
mod http;
|
mod http;
|
||||||
use std::{fs, path::PathBuf};
|
mod iw4x;
|
||||||
|
mod misc;
|
||||||
|
mod self_update;
|
||||||
|
mod structs;
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
use global::*;
|
||||||
struct CdnFile {
|
use structs::*;
|
||||||
name: String,
|
|
||||||
size: u32,
|
use colored::*;
|
||||||
hash: String,
|
#[cfg(windows)]
|
||||||
|
use mslnk::ShellLink;
|
||||||
|
use std::{borrow::Cow, collections::HashMap, fs, path::Path, path::PathBuf};
|
||||||
|
#[cfg(windows)]
|
||||||
|
use steamlocate::SteamDir;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn get_installed_games(games: &Vec<Game>) -> Vec<(u32, PathBuf)> {
|
||||||
|
let mut installed_games = Vec::new();
|
||||||
|
let mut steamdir = match SteamDir::locate() {
|
||||||
|
Some(steamdir) => steamdir,
|
||||||
|
None => {
|
||||||
|
println!("{}", "Steam not found!".yellow());
|
||||||
|
return installed_games;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for game in games {
|
||||||
|
if let Some(app) = steamdir.app(&game.app_id) {
|
||||||
|
installed_games.push((game.app_id, PathBuf::from(&app.path)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
installed_games
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[cfg(windows)]
|
||||||
struct Game<'a> {
|
fn setup_client_links(game: &Game, game_dir: &Path) {
|
||||||
engine: &'a str,
|
if game.client.len() > 1 {
|
||||||
client: &'a str,
|
println!("Multiple clients installed, use the shortcuts (launch-<client>.lnk in the game directory or on the desktop) to launch a specific client.");
|
||||||
references: Vec<&'a str>,
|
}
|
||||||
|
|
||||||
|
let target = game_dir.join("alterware-launcher.exe");
|
||||||
|
|
||||||
|
for c in game.client.iter() {
|
||||||
|
let lnk = game_dir.join(format!("launch-{}.lnk", c));
|
||||||
|
|
||||||
|
let mut sl = ShellLink::new(target.clone()).unwrap();
|
||||||
|
sl.set_arguments(Some(c.to_string()));
|
||||||
|
sl.set_icon_location(Some(
|
||||||
|
game_dir
|
||||||
|
.join(format!("{}.exe", c))
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned(),
|
||||||
|
));
|
||||||
|
sl.create_lnk(&lnk).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MASTER: &str = "https://master.alterware.dev";
|
#[cfg(windows)]
|
||||||
|
fn setup_desktop_links(path: &Path, game: &Game) {
|
||||||
|
println!("Create Desktop shortcut? (Y/n)");
|
||||||
|
let input = misc::stdin().to_ascii_lowercase();
|
||||||
|
|
||||||
fn file_get_sha1(path: &PathBuf) -> String {
|
if input == "y" || input.is_empty() {
|
||||||
let mut sha1 = sha1_smol::Sha1::new();
|
let desktop = PathBuf::from(&format!(
|
||||||
sha1.update(&fs::read(path).unwrap());
|
"{}\\Desktop",
|
||||||
sha1.digest().to_string()
|
std::env::var("USERPROFILE").unwrap()
|
||||||
|
));
|
||||||
|
|
||||||
|
let target = path.join("alterware-launcher.exe");
|
||||||
|
|
||||||
|
for c in game.client.iter() {
|
||||||
|
let lnk = desktop.join(format!("{}.lnk", c));
|
||||||
|
|
||||||
|
let mut sl = ShellLink::new(target.clone()).unwrap();
|
||||||
|
sl.set_arguments(Some(c.to_string()));
|
||||||
|
sl.set_icon_location(Some(
|
||||||
|
path.join(format!("{}.exe", c))
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned(),
|
||||||
|
));
|
||||||
|
sl.create_lnk(lnk).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(game: &Game) {
|
#[cfg(windows)]
|
||||||
let cdn_info: Vec<CdnFile> = serde_json::from_str(&http::get_body_string(
|
fn auto_install(path: &Path, game: &Game) {
|
||||||
format!(
|
setup_client_links(game, path);
|
||||||
"{}/files.json?{}",
|
setup_desktop_links(path, game);
|
||||||
MASTER,
|
update(game, path, false, false);
|
||||||
rand::Rng::gen_range(&mut rand::thread_rng(), 0..1000)
|
}
|
||||||
)
|
|
||||||
.as_str(),
|
#[cfg(windows)]
|
||||||
))
|
fn windows_launcher_install(games: &Vec<Game>) {
|
||||||
.unwrap();
|
println!(
|
||||||
|
"{}",
|
||||||
|
"No game specified/found. Checking for installed Steam games..".yellow()
|
||||||
|
);
|
||||||
|
let installed_games = get_installed_games(games);
|
||||||
|
|
||||||
|
if !installed_games.is_empty() {
|
||||||
|
let current_dir = std::env::current_dir().unwrap();
|
||||||
|
for (id, path) in installed_games.iter() {
|
||||||
|
if current_dir.starts_with(path) {
|
||||||
|
println!("Found game in current directory.");
|
||||||
|
println!("Installing AlterWare client for {}.", id);
|
||||||
|
let game = games.iter().find(|&g| g.app_id == *id).unwrap();
|
||||||
|
auto_install(path, game);
|
||||||
|
println!("Installation complete. Please run the launcher again or use a shortcut to launch the game.");
|
||||||
|
std::io::stdin().read_line(&mut String::new()).unwrap();
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Installed games:");
|
||||||
|
|
||||||
|
for (id, path) in installed_games.iter() {
|
||||||
|
println!("{}: {}", id, path.display());
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Enter the ID of the game you want to install the AlterWare client for, enter 0 for manual selection:");
|
||||||
|
let input: u32 = misc::stdin().parse().unwrap();
|
||||||
|
|
||||||
|
if input == 0 {
|
||||||
|
return manual_install(games);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (id, path) in installed_games.iter() {
|
||||||
|
if *id == input {
|
||||||
|
let game = games.iter().find(|&g| g.app_id == input).unwrap();
|
||||||
|
|
||||||
|
let launcher_path = std::env::current_exe().unwrap();
|
||||||
|
let target_path = path.join("alterware-launcher.exe");
|
||||||
|
|
||||||
|
if launcher_path != target_path {
|
||||||
|
fs::copy(launcher_path, target_path).unwrap();
|
||||||
|
println!("Launcher copied to {}", path.display());
|
||||||
|
}
|
||||||
|
auto_install(path, game);
|
||||||
|
println!("Installation complete. Please run the launcher again or use a shortcut to launch the game.");
|
||||||
|
std::io::stdin().read_line(&mut String::new()).unwrap();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::process::exit(0);
|
||||||
|
} else {
|
||||||
|
manual_install(games);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prompt_client_selection(games: &[Game]) -> String {
|
||||||
|
println!(
|
||||||
|
"Couldn't detect any games, please select a client to install in the current directory:"
|
||||||
|
);
|
||||||
|
for (i, g) in games.iter().enumerate() {
|
||||||
|
for c in g.client.iter() {
|
||||||
|
println!("{}: {}", i, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let input: usize = misc::stdin().parse().unwrap();
|
||||||
|
String::from(games[input].client[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn manual_install(games: &[Game]) {
|
||||||
|
let selection = prompt_client_selection(games);
|
||||||
|
let game = games.iter().find(|&g| g.client[0] == selection).unwrap();
|
||||||
|
update(game, &std::env::current_dir().unwrap(), false, false);
|
||||||
|
println!("Installation complete. Please run the launcher again or use a shortcut to launch the game.");
|
||||||
|
std::io::stdin().read_line(&mut String::new()).unwrap();
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_dir(
|
||||||
|
cdn_info: &Vec<CdnFile>,
|
||||||
|
remote_dir: &str,
|
||||||
|
dir: &Path,
|
||||||
|
hashes: &mut HashMap<String, String>,
|
||||||
|
) {
|
||||||
|
let remote_dir = format!("{}/", remote_dir);
|
||||||
|
|
||||||
let mut files_to_update: Vec<CdnFile> = Vec::new();
|
|
||||||
for file in cdn_info {
|
for file in cdn_info {
|
||||||
if file.name.starts_with(game.engine) {
|
if !file.name.starts_with(&remote_dir) || file.name == "iw4/iw4x.dll" {
|
||||||
files_to_update.push(file);
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for file in files_to_update {
|
|
||||||
let file_path = PathBuf::from(&file.name.replace(&format!("{}/", game.engine), ""));
|
|
||||||
if file_path.exists() {
|
|
||||||
let sha1_local = file_get_sha1(&file_path).to_lowercase();
|
|
||||||
let sha1_remote = file.hash.to_lowercase();
|
let sha1_remote = file.hash.to_lowercase();
|
||||||
|
let file_name = &file.name.replace(remote_dir.as_str(), "");
|
||||||
|
let file_path = dir.join(file_name);
|
||||||
|
if file_path.exists() {
|
||||||
|
let sha1_local = hashes
|
||||||
|
.get(file_name)
|
||||||
|
.map(Cow::Borrowed)
|
||||||
|
.unwrap_or_else(|| Cow::Owned(misc::get_file_sha1(&file_path)))
|
||||||
|
.to_string();
|
||||||
|
|
||||||
if sha1_local != sha1_remote {
|
if sha1_local != sha1_remote {
|
||||||
println!(
|
println!(
|
||||||
"Updating {}...\nLocal hash: {}\nRemote hash: {}",
|
"[{}] {}",
|
||||||
file_path.display(),
|
"Updating".bright_yellow(),
|
||||||
sha1_local,
|
file_path.display()
|
||||||
sha1_remote
|
|
||||||
);
|
);
|
||||||
http::download_file(
|
http::download_file(&format!("{}/{}", MASTER, file.name), &file_path);
|
||||||
&format!(
|
|
||||||
"{}/{}?{}",
|
|
||||||
MASTER,
|
|
||||||
file.name,
|
|
||||||
rand::Rng::gen_range(&mut rand::thread_rng(), 0..1000)
|
|
||||||
),
|
|
||||||
&file_path,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
println!("Downloading {}...", file_path.display());
|
println!("[{}] {}", "Checked".bright_blue(), file_path.display());
|
||||||
|
}
|
||||||
|
hashes.insert(file_name.to_owned(), sha1_remote.to_owned());
|
||||||
|
} else {
|
||||||
|
println!(
|
||||||
|
"[{}] {}",
|
||||||
|
"Downloading".bright_yellow(),
|
||||||
|
file_path.display()
|
||||||
|
);
|
||||||
if let Some(parent) = file_path.parent() {
|
if let Some(parent) = file_path.parent() {
|
||||||
if !parent.exists() {
|
if !parent.exists() {
|
||||||
fs::create_dir_all(parent).unwrap();
|
fs::create_dir_all(parent).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
http::download_file(
|
http::download_file(&format!("{}/{}", MASTER, file.name), &file_path);
|
||||||
&format!(
|
hashes.insert(file_name.to_owned(), sha1_remote.to_owned());
|
||||||
"{}/{}?{}",
|
|
||||||
MASTER,
|
|
||||||
file.name,
|
|
||||||
rand::Rng::gen_range(&mut rand::thread_rng(), 0..1000)
|
|
||||||
),
|
|
||||||
&file_path,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn launch(file_path: &PathBuf) {
|
fn update(game: &Game, dir: &Path, bonus_content: bool, force: bool) {
|
||||||
println!("Launching {}...", file_path.display());
|
let cdn_info: Vec<CdnFile> = serde_json::from_str(&http::get_body_string(
|
||||||
std::process::Command::new(file_path)
|
format!("{}/files.json", MASTER).as_str(),
|
||||||
.spawn()
|
))
|
||||||
.unwrap()
|
|
||||||
.wait()
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let mut hashes = HashMap::new();
|
||||||
|
let hash_file = dir.join(".sha-sums");
|
||||||
|
if hash_file.exists() && !force {
|
||||||
|
let hash_file = fs::read_to_string(hash_file).unwrap();
|
||||||
|
for line in hash_file.lines() {
|
||||||
|
let mut split = line.split_whitespace();
|
||||||
|
let hash = split.next().unwrap();
|
||||||
|
let file = split.next().unwrap();
|
||||||
|
hashes.insert(file.to_owned(), hash.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_dir(&cdn_info, game.engine, dir, &mut hashes);
|
||||||
|
|
||||||
|
if game.engine == "iw4" {
|
||||||
|
iw4x::update(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if bonus_content && !game.bonus.is_empty() {
|
||||||
|
for bonus in game.bonus.iter() {
|
||||||
|
update_dir(&cdn_info, bonus, dir, &mut hashes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut hash_file_content = String::new();
|
||||||
|
for (file, hash) in hashes.iter() {
|
||||||
|
hash_file_content.push_str(&format!("{} {}\n", hash, file));
|
||||||
|
}
|
||||||
|
fs::write(dir.join(".sha-sums"), hash_file_content).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn launch(file_path: &PathBuf, args: &str) {
|
||||||
|
println!("Launching {} {}", file_path.display(), args);
|
||||||
|
std::process::Command::new(file_path)
|
||||||
|
.args(args.trim().split(' '))
|
||||||
|
.current_dir(file_path.parent().unwrap())
|
||||||
|
.spawn()
|
||||||
|
.expect("Failed to launch the game")
|
||||||
|
.wait()
|
||||||
|
.expect("Failed to wait for the game process to finish");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn setup_env() {
|
||||||
|
colored::control::set_virtual_terminal(true).unwrap_or_else(|error| {
|
||||||
|
println!("{:#?}", error);
|
||||||
|
colored::control::SHOULD_COLORIZE.set_override(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arg_value(args: &[String], arg: &str) -> Option<String> {
|
||||||
|
args.iter()
|
||||||
|
.position(|r| r == arg)
|
||||||
|
.map(|e| args[e + 1].clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arg_bool(args: &[String], arg: &str) -> bool {
|
||||||
|
args.iter().any(|r| r == arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arg_remove(args: &mut Vec<String>, arg: &str) {
|
||||||
|
args.iter().position(|r| r == arg).map(|e| args.remove(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arg_remove_value(args: &mut Vec<String>, arg: &str) {
|
||||||
|
if let Some(e) = args.iter().position(|r| r == arg) {
|
||||||
|
args.remove(e);
|
||||||
|
args.remove(e);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
#[cfg(windows)]
|
||||||
|
setup_env();
|
||||||
|
|
||||||
let mut args: Vec<String> = std::env::args().collect();
|
let mut args: Vec<String> = std::env::args().collect();
|
||||||
|
|
||||||
|
if arg_bool(&args, "--help") {
|
||||||
|
println!("CLI Args:");
|
||||||
|
println!(" <client>: Specify the client to launch");
|
||||||
|
println!(" --help: Display this help message");
|
||||||
|
println!(" --version: Display the launcher version");
|
||||||
|
println!(" --path/-p <path>: Specify the game directory");
|
||||||
|
println!(" --update/-u: Update only, don't launch the game");
|
||||||
|
println!(" --bonus: Download bonus content");
|
||||||
|
println!(" --force/-f: Force file hash recheck");
|
||||||
|
println!(" --pass <args>: Pass arguments to the game");
|
||||||
|
println!(" --skip-launcher-update: Skip launcher self-update");
|
||||||
|
println!(
|
||||||
|
"\nExample:\n alterware-launcher.exe iw4x --bonus --pass \"-console -nointro\""
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg_bool(&args, "--version") || arg_bool(&args, "-v") {
|
||||||
|
println!(
|
||||||
|
"{} v{}",
|
||||||
|
"AlterWare Launcher".bright_green(),
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
);
|
||||||
|
println!("https://github.com/{}/{}", GH_OWNER, GH_REPO);
|
||||||
|
println!(
|
||||||
|
"\n{}{}{}{}{}{}{}",
|
||||||
|
"For ".on_black(),
|
||||||
|
"Alter".bright_blue().on_black().underline(),
|
||||||
|
"Ware".white().on_black().underline(),
|
||||||
|
".dev".on_black().underline(),
|
||||||
|
" by ".on_black(),
|
||||||
|
"mxve".bright_magenta().on_black().underline(),
|
||||||
|
".de".on_black().underline()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let install_path: PathBuf;
|
||||||
|
if let Some(path) = arg_value(&args, "--path") {
|
||||||
|
install_path = PathBuf::from(path);
|
||||||
|
arg_remove_value(&mut args, "--path");
|
||||||
|
} else if let Some(path) = arg_value(&args, "-p") {
|
||||||
|
install_path = PathBuf::from(path);
|
||||||
|
arg_remove_value(&mut args, "-p");
|
||||||
|
} else {
|
||||||
|
install_path = std::env::current_dir().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut cfg = config::load(install_path.join("alterware-launcher.json"));
|
||||||
|
|
||||||
|
if !arg_bool(&args, "--skip-launcher-update") && !cfg.skip_self_update {
|
||||||
|
self_update::run(cfg.update_only);
|
||||||
|
} else {
|
||||||
|
arg_remove(&mut args, "--skip-launcher-update");
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg_bool(&args, "--update") || arg_bool(&args, "-u") {
|
||||||
|
cfg.update_only = true;
|
||||||
|
arg_remove(&mut args, "--update");
|
||||||
|
arg_remove(&mut args, "-u");
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg_bool(&args, "--bonus") {
|
||||||
|
cfg.download_bonus_content = true;
|
||||||
|
cfg.ask_bonus_content = false;
|
||||||
|
arg_remove(&mut args, "--bonus");
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg_bool(&args, "--force") || arg_bool(&args, "-f") {
|
||||||
|
cfg.force_update = true;
|
||||||
|
arg_remove(&mut args, "--force");
|
||||||
|
arg_remove(&mut args, "-f");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(pass) = arg_value(&args, "--pass") {
|
||||||
|
cfg.args = pass;
|
||||||
|
arg_remove_value(&mut args, "--pass");
|
||||||
|
} else if cfg.args.is_empty() {
|
||||||
|
cfg.args = String::from("");
|
||||||
|
}
|
||||||
|
|
||||||
let games_json = http::get_body_string(format!("{}/games.json", MASTER).as_str());
|
let games_json = http::get_body_string(format!("{}/games.json", MASTER).as_str());
|
||||||
let games: Vec<Game> = serde_json::from_str(&games_json).unwrap();
|
let games: Vec<Game> = serde_json::from_str(&games_json).unwrap();
|
||||||
|
|
||||||
let mut update_only = false;
|
|
||||||
if args.contains(&String::from("update")) {
|
|
||||||
update_only = true;
|
|
||||||
args.iter()
|
|
||||||
.position(|r| r == "update")
|
|
||||||
.map(|e| args.remove(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut game: String = String::new();
|
let mut game: String = String::new();
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
game = String::from(&args[1]);
|
game = String::from(&args[1]);
|
||||||
} else {
|
} else {
|
||||||
'main: for g in games.iter() {
|
'main: for g in games.iter() {
|
||||||
for r in g.references.iter() {
|
for r in g.references.iter() {
|
||||||
if std::path::Path::new(r).exists() {
|
if install_path.join(r).exists() {
|
||||||
game = String::from(g.client);
|
if g.client.len() > 1 {
|
||||||
|
if cfg.update_only {
|
||||||
|
game = String::from(g.client[0]);
|
||||||
|
break 'main;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
setup_client_links(g, &std::env::current_dir().unwrap());
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
println!("Multiple clients installed, set the client as the first argument to launch a specific client.");
|
||||||
|
println!("Select a client to launch:");
|
||||||
|
for (i, c) in g.client.iter().enumerate() {
|
||||||
|
println!("{}: {}", i, c);
|
||||||
|
}
|
||||||
|
game = String::from(g.client[misc::stdin().parse::<usize>().unwrap()]);
|
||||||
|
break 'main;
|
||||||
|
}
|
||||||
|
game = String::from(g.client[0]);
|
||||||
break 'main;
|
break 'main;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,17 +426,45 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for g in games.iter() {
|
for g in games.iter() {
|
||||||
if g.client == game {
|
for c in g.client.iter() {
|
||||||
update(g);
|
if c == &game {
|
||||||
if update_only {
|
if cfg.ask_bonus_content && !g.bonus.is_empty() {
|
||||||
|
println!("Download bonus content? (Y/n)");
|
||||||
|
let input = misc::stdin().to_ascii_lowercase();
|
||||||
|
cfg.download_bonus_content = input != "n";
|
||||||
|
config::save_value(
|
||||||
|
install_path.join("alterware-launcher.json"),
|
||||||
|
"download_bonus_content",
|
||||||
|
cfg.download_bonus_content,
|
||||||
|
);
|
||||||
|
config::save_value(
|
||||||
|
install_path.join("alterware-launcher.json"),
|
||||||
|
"ask_bonus_content",
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(
|
||||||
|
g,
|
||||||
|
install_path.as_path(),
|
||||||
|
cfg.download_bonus_content,
|
||||||
|
cfg.force_update,
|
||||||
|
);
|
||||||
|
if !cfg.update_only {
|
||||||
|
launch(&install_path.join(format!("{}.exe", c)), &cfg.args);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
launch(&PathBuf::from(format!("{}.exe", g.client)));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Game not found!");
|
#[cfg(windows)]
|
||||||
|
windows_launcher_install(&games);
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
manual_install(&games);
|
||||||
|
|
||||||
|
println!("{}", "Game not found!".bright_red());
|
||||||
println!("Place the launcher in the game folder, if that doesn't work specify the client on the command line (ex. alterware-launcher.exe iw4-sp)");
|
println!("Place the launcher in the game folder, if that doesn't work specify the client on the command line (ex. alterware-launcher.exe iw4-sp)");
|
||||||
println!("Press enter to exit...");
|
println!("Press enter to exit...");
|
||||||
std::io::stdin().read_line(&mut String::new()).unwrap();
|
std::io::stdin().read_line(&mut String::new()).unwrap();
|
||||||
|
20
src/misc.rs
Normal file
20
src/misc.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
|
pub fn get_file_sha1(path: &PathBuf) -> String {
|
||||||
|
let mut sha1 = sha1_smol::Sha1::new();
|
||||||
|
sha1.update(&fs::read(path).unwrap());
|
||||||
|
sha1.digest().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stdin() -> String {
|
||||||
|
let mut input = String::new();
|
||||||
|
std::io::stdin().read_line(&mut input).unwrap();
|
||||||
|
input.trim().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rev_to_int(rev: &str) -> u16 {
|
||||||
|
rev.strip_prefix('r')
|
||||||
|
.unwrap_or("0")
|
||||||
|
.parse::<u16>()
|
||||||
|
.unwrap_or(0)
|
||||||
|
}
|
91
src/self_update.rs
Normal file
91
src/self_update.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use crate::github;
|
||||||
|
use crate::global::*;
|
||||||
|
|
||||||
|
use semver::Version;
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
|
pub fn self_update_available() -> bool {
|
||||||
|
let current_version: Version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||||
|
let latest_version = github::latest_version(GH_OWNER, GH_REPO);
|
||||||
|
|
||||||
|
current_version < latest_version
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
pub fn run(_update_only: bool) {
|
||||||
|
if self_update_available() {
|
||||||
|
println!("A new version of the AlterWare launcher is available.");
|
||||||
|
println!(
|
||||||
|
"Download it at {}",
|
||||||
|
github::latest_release_url(GH_OWNER, GH_REPO)
|
||||||
|
);
|
||||||
|
println!("Launching in 10 seconds..");
|
||||||
|
thread::sleep(time::Duration::from_secs(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn run(update_only: bool) {
|
||||||
|
use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
|
use crate::http;
|
||||||
|
|
||||||
|
let working_dir = std::env::current_dir().unwrap();
|
||||||
|
let files = fs::read_dir(&working_dir).unwrap();
|
||||||
|
|
||||||
|
for file in files {
|
||||||
|
let file = file.unwrap();
|
||||||
|
let file_name = file.file_name().into_string().unwrap();
|
||||||
|
|
||||||
|
if file_name.contains("alterware-launcher")
|
||||||
|
&& (file_name.contains(".__relocated__.exe")
|
||||||
|
|| file_name.contains(".__selfdelete__.exe"))
|
||||||
|
{
|
||||||
|
fs::remove_file(file.path()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self_update_available() {
|
||||||
|
println!("Performing launcher self-update.");
|
||||||
|
println!(
|
||||||
|
"If you run into any issues, please download the latest version at {}",
|
||||||
|
github::latest_release_url(GH_OWNER, GH_REPO)
|
||||||
|
);
|
||||||
|
|
||||||
|
let update_binary = PathBuf::from("alterware-launcher-update.exe");
|
||||||
|
let file_path = working_dir.join(&update_binary);
|
||||||
|
|
||||||
|
if update_binary.exists() {
|
||||||
|
fs::remove_file(&update_binary).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let launcher_name = if cfg!(target_arch = "x86") {
|
||||||
|
"alterware-launcher-x86.exe"
|
||||||
|
} else {
|
||||||
|
"alterware-launcher.exe"
|
||||||
|
};
|
||||||
|
println!("{}", launcher_name);
|
||||||
|
http::download_file(
|
||||||
|
&format!(
|
||||||
|
"{}/download/{}",
|
||||||
|
github::latest_release_url(GH_OWNER, GH_REPO),
|
||||||
|
launcher_name
|
||||||
|
),
|
||||||
|
&file_path,
|
||||||
|
);
|
||||||
|
|
||||||
|
if !file_path.exists() {
|
||||||
|
println!("Failed to download launcher update.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self_replace::self_replace("alterware-launcher-update.exe").unwrap();
|
||||||
|
fs::remove_file(&file_path).unwrap();
|
||||||
|
println!("Launcher updated. Please run it again.");
|
||||||
|
if !update_only {
|
||||||
|
std::io::stdin().read_line(&mut String::new()).unwrap();
|
||||||
|
}
|
||||||
|
std::process::exit(201);
|
||||||
|
}
|
||||||
|
}
|
38
src/structs.rs
Normal file
38
src/structs.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct CdnFile {
|
||||||
|
pub name: String,
|
||||||
|
pub size: u32,
|
||||||
|
pub hash: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct Game<'a> {
|
||||||
|
pub engine: &'a str,
|
||||||
|
pub client: Vec<&'a str>,
|
||||||
|
pub references: Vec<&'a str>,
|
||||||
|
pub app_id: u32,
|
||||||
|
pub bonus: Vec<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct Config {
|
||||||
|
pub update_only: bool,
|
||||||
|
pub skip_self_update: bool,
|
||||||
|
pub download_bonus_content: bool,
|
||||||
|
pub ask_bonus_content: bool,
|
||||||
|
pub force_update: bool,
|
||||||
|
pub args: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
update_only: false,
|
||||||
|
skip_self_update: false,
|
||||||
|
download_bonus_content: false,
|
||||||
|
ask_bonus_content: true,
|
||||||
|
force_update: false,
|
||||||
|
args: String::from(""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user