#272 Mod Support (#276)

* Added nexus mods and downloader

* Mod downloader ready

* Modified to follow redirect information

* Slimmed down env

* Running with type message fix

* dynamic fetch of latest bepinex version

* Refactored file

* Changes

* Dont use barrow

* Added support for downloading dll and cfg

* Added exit for non zip file
This commit is contained in:
Michael
2021-03-14 18:39:11 -07:00
committed by GitHub
parent 8c5f642da7
commit 29f272ff7f
20 changed files with 870 additions and 360 deletions

View File

@@ -1,5 +1,7 @@
.github/
.idea/
.run/
target/
tmp/
docs/
.github/

261
Cargo.lock generated
View File

@@ -1,10 +1,10 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "adler"
version = "0.2.3"
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "atty"
@@ -47,12 +47,39 @@ version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
[[package]]
name = "bzip2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b"
dependencies = [
"bzip2-sys",
"libc",
]
[[package]]
name = "bzip2-sys"
version = "0.1.10+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17fa3d1ac1ca21c5c4e36a97f3c3eb25084576f6fc47bf0139c1123434216c6c"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "cargo-husky"
version = "1.5.0"
@@ -65,6 +92,12 @@ version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -129,7 +162,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
]
[[package]]
@@ -154,7 +187,7 @@ version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
]
[[package]]
@@ -163,7 +196,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
"libc",
"redox_syscall",
"winapi",
@@ -171,11 +204,11 @@ dependencies = [
[[package]]
name = "flate2"
version = "1.0.20"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0"
checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"crc32fast",
"libc",
"miniz_oxide",
@@ -198,31 +231,37 @@ dependencies = [
]
[[package]]
name = "futures-channel"
version = "0.3.12"
name = "fs_extra"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846"
checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394"
[[package]]
name = "futures-channel"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.12"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65"
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
[[package]]
name = "futures-io"
version = "0.3.12"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500"
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
[[package]]
name = "futures-macro"
version = "0.3.12"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd"
checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7"
dependencies = [
"proc-macro-hack",
"proc-macro2",
@@ -232,24 +271,21 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.12"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6"
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
[[package]]
name = "futures-task"
version = "0.3.12"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86"
dependencies = [
"once_cell",
]
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
[[package]]
name = "futures-util"
version = "0.3.12"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b"
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
dependencies = [
"futures-core",
"futures-io",
@@ -269,16 +305,16 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
"libc",
"wasi",
]
[[package]]
name = "h2"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b67e66362108efccd8ac053abafc8b7a8d86a37e6e48fc4f6f7485eb5e9e6a5"
checksum = "d832b01df74254fe364568d6ddc294443f61cbec82816b60904303af87efae78"
dependencies = [
"bytes",
"fnv",
@@ -291,7 +327,6 @@ dependencies = [
"tokio",
"tokio-util",
"tracing",
"tracing-futures",
]
[[package]]
@@ -403,9 +438,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.6.1"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
dependencies = [
"autocfg",
"hashbrown",
@@ -423,7 +458,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
]
[[package]]
@@ -440,9 +475,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "js-sys"
version = "0.3.47"
version = "0.3.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65"
checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78"
dependencies = [
"wasm-bindgen",
]
@@ -455,9 +490,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.86"
version = "0.2.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a"
[[package]]
name = "linked-hash-map"
@@ -480,7 +515,7 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
]
[[package]]
@@ -489,6 +524,12 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
[[package]]
name = "md5"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
[[package]]
name = "memchr"
version = "2.3.4"
@@ -503,19 +544,18 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "miniz_oxide"
version = "0.4.3"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
dependencies = [
"adler",
"autocfg",
"adler32",
]
[[package]]
name = "mio"
version = "0.7.8"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc250d6848c90d719ea2ce34546fb5df7af1d3fd189d10bf7bad80bfcebecd95"
checksum = "a5dede4e2065b3842b8b0af444119f3aa331cc7cc2dd20388bfb0f5d5a38823a"
dependencies = [
"libc",
"log",
@@ -574,15 +614,17 @@ dependencies = [
[[package]]
name = "odin"
version = "1.3.0"
version = "1.4.0"
dependencies = [
"cargo-husky",
"chrono",
"clap",
"daemonize",
"flate2",
"fs_extra",
"inflections",
"log",
"md5",
"once_cell",
"rand",
"reqwest",
@@ -592,13 +634,14 @@ dependencies = [
"sysinfo",
"tar",
"which",
"zip",
]
[[package]]
name = "once_cell"
version = "1.7.0"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
[[package]]
name = "os_str_bytes"
@@ -623,7 +666,7 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
"instant",
"libc",
"redox_syscall",
@@ -659,9 +702,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
version = "0.2.4"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827"
checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
[[package]]
name = "pin-utils"
@@ -669,6 +712,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
@@ -780,9 +829,9 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.11.1"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0460542b551950620a3648c6aa23318ac6b3cd779114bd873209e6e8b5eb1c34"
checksum = "bf12057f289428dbf5c591c74bf10392e4a8003f993405a902f20117019022d4"
dependencies = [
"base64",
"bytes",
@@ -866,18 +915,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.123"
version = "1.0.124"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.123"
version = "1.0.124"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b"
dependencies = [
"proc-macro2",
"quote",
@@ -886,9 +935,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.62"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
dependencies = [
"itoa",
"ryu",
@@ -947,7 +996,7 @@ version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
"libc",
"winapi",
]
@@ -966,9 +1015,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.60"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
dependencies = [
"proc-macro2",
"quote",
@@ -977,11 +1026,11 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.16.2"
version = "0.16.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a474f92030c61f32a21f4b3370c6f25c710e55b2ea9e64dd9ed4f1cd5e734d9b"
checksum = "6c280c91abd1aed2e36be1bc8f56fbc7a2acbb2b58fbcac9641510179cc72dd9"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
"core-foundation-sys",
"doc-comment",
"libc",
@@ -992,9 +1041,9 @@ dependencies = [
[[package]]
name = "tar"
version = "0.4.32"
version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0313546c01d59e29be4f09687bcb4fb6690cec931cc3607b6aec7a0e417f4cc6"
checksum = "c0bcfbd6a598361fda270d82469fff3d65089dc33e175c9a131f7b4cd395f228"
dependencies = [
"filetime",
"libc",
@@ -1021,18 +1070,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote",
@@ -1066,9 +1115,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.2.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a"
checksum = "8d56477f6ed99e10225f38f9f75f872f29b8b8bd8c0b946f63345bb144e9eeda"
dependencies = [
"autocfg",
"bytes",
@@ -1092,9 +1141,9 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.6.3"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebb7cb2f00c5ae8df755b252306272cd1790d39728363936e01827e11f0b017b"
checksum = "ec31e5cc6b46e653cf57762f36f71d5e6386391d88a72fd6db4508f8f676fb29"
dependencies = [
"bytes",
"futures-core",
@@ -1112,11 +1161,11 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.24"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f77d3842f76ca899ff2dbcf231c5c65813dea431301d6eb686279c15c4464f12"
checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
"pin-project-lite",
"tracing-core",
]
@@ -1130,16 +1179,6 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "tracing-futures"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
dependencies = [
"pin-project",
"tracing",
]
[[package]]
name = "try-lock"
version = "0.2.3"
@@ -1230,11 +1269,11 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasm-bindgen"
version = "0.2.70"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
"serde",
"serde_json",
"wasm-bindgen-macro",
@@ -1242,9 +1281,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.70"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7"
checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8"
dependencies = [
"bumpalo",
"lazy_static",
@@ -1257,11 +1296,11 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.20"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3de431a2910c86679c34283a33f66f4e4abd7e0aec27b6669060148872aadf94"
checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
"js-sys",
"wasm-bindgen",
"web-sys",
@@ -1269,9 +1308,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.70"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1279,9 +1318,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.70"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e"
dependencies = [
"proc-macro2",
"quote",
@@ -1292,15 +1331,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.70"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64"
checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1"
[[package]]
name = "web-sys"
version = "0.3.47"
version = "0.3.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3"
checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -1392,3 +1431,17 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]
[[package]]
name = "zip"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8264fcea9b7a036a4a5103d7153e988dbc2ebbafb34f68a3c2d404b6b82d74b6"
dependencies = [
"byteorder",
"bzip2",
"crc32fast",
"flate2",
"thiserror",
"time",
]

View File

@@ -1,7 +1,7 @@
[package]
name = "odin"
version = "1.3.0"
authors = ["mbround18 <12646562+mbround18@users.noreply.github.com>"]
version = "1.4.0"
authors = ["mbround18"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -19,6 +19,10 @@ flate2 = "1.0"
inflections = "1.1.1"
reqwest = { version = "0.11.1", default_features = false, features = ["blocking", "json", "rustls-tls"] }
chrono = "0.4"
md5 = "0.7.0"
zip = { version = "0.5" }
fs_extra = "1.2.0"
[dev-dependencies]
once_cell = "1.7"

View File

@@ -10,6 +10,7 @@ FROM mbround18/valheim-odin:${ODIN_IMAGE_VERSION} as runtime
FROM cm2network/steamcmd:root
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y \
htop net-tools nano gcc g++ gdb \
netcat curl wget zip unzip \
@@ -45,7 +46,12 @@ ENV PUID=1000 \
AUTO_BACKUP_DAYS_TO_LIVE="3" \
AUTO_BACKUP_ON_UPDATE="0" \
AUTO_BACKUP_ON_SHUTDOWN="0" \
UPDATE_ON_STARTUP="1"
UPDATE_ON_STARTUP="1" \
SAVE_LOCATION="/home/steam/.config/unity3d/IronGate/Valheim" \
MODS_LOCATION="/home/steam/staging/mods" \
GAME_LOCATION="/home/steam/valheim" \
BACKUP_LOCATION="/home/steam/backups" \
TYPE="Vanilla"
COPY ./src/scripts/*.sh /home/steam/scripts/
COPY ./src/scripts/entrypoint.sh /entrypoint.sh

View File

@@ -23,6 +23,18 @@
> Modding is not supported by the Valheim developers officially yet; Which means you WILL run into errors. This repo has been tested with running ValheimPlus as a test mod and does not have any issues.
> See [Getting started with mods]
### Download Locations
#### DockerHub
<a href="https://hub.docker.com/r/mbround18/valheim"><img alt="DockerHub Valheim" src="https://img.shields.io/badge/DockerHub-Valheim-blue?style=for-the-badge"></a>
<a href="https://hub.docker.com/r/mbround18/valheim-odin"><img alt="DockerHub Odin" src="https://img.shields.io/badge/DockerHub-Odin-blue?style=for-the-badge"></a>
#### GitHub Container Registry
<a href="https://github.com/users/mbround18/packages/container/package/valheim"><img alt="GHCR Valheim" src="https://img.shields.io/badge/GHCR-Valheim-blue?style=for-the-badge"></a>
<a href="https://github.com/users/mbround18/packages/container/package/valheim-odin"><img alt="GHCR Odin" src="https://img.shields.io/badge/GHCR-Odin-blue?style=for-the-badge"></a>
### Environment Variables
> See further on down for advanced environment variables.
@@ -37,6 +49,8 @@
| WORLD | `Dedicated` | TRUE | This is used to generate the name of your world. |
| PUBLIC | `1` | FALSE | Sets whether or not your server is public on the server list. |
| PASSWORD | `12345` | TRUE | Set this to something unique! |
| TYPE | `Vanilla` | FALSE | This can be set to `ValheimPlus`, `BepInEx`, `BepInExFull` or `Vanilla` |
| MODS | ` ` | FALSE | This is an array of mods separated by comma and a new line. [Click Here for Examples](./docs/getting_started_with_mods.md) Supported files are `zip`, `dll`, and `cfg`. |
| AUTO_UPDATE | `0` | FALSE | Set to `1` if you want your container to auto update! This means at the times indicated by `AUTO_UPDATE_SCHEDULE` it will check for server updates. If there is an update then the server will be shut down, updated, and brought back online if the server was running before. |
| AUTO_UPDATE_SCHEDULE | `0 1 * * *` | FALSE | This works in conjunction with `AUTO_UPDATE` and sets the schedule to which it will run an auto update. [If you need help figuring out a cron schedule click here]
| AUTO_BACKUP | `0` | FALSE | Set to `1` to enable auto backups. Backups are stored under `/home/steam/backups` which means you will have to add a volume mount for this directory. |
@@ -52,7 +66,7 @@
#### Simple
> This is a basic example of a docker compose, you can apply any of the variables above to the `environment` section below but be sure to follow each variables description notes!
> This is a basic example of a docker compose, you can apply any of the variables above to the `environment` section below but be sure to follow each variables' description notes!
```yaml
version: "3"
@@ -156,7 +170,9 @@ If you would like to have release notifications tied into your Discord server, c
- latest (Stable):
- [#100] Added backup feature to run based on cronjob.
- [#148] Added Mod support
- Added webhook configuration and documentation updates [#158]
- [#158] Added webhook configuration and documentation updates
- [#236] Now [publish to github registry as well](https://github.com/users/mbround18/packages/container/package/valheim)
- [#276] Advanced mod support with auto installer
- 1.2.0 (Stable):
- Readme update to include the versions section and environment variables section.
- [#18] Changed to `root` as the default user to allow updated steams User+Group IDs.
@@ -183,6 +199,8 @@ If you would like to have release notifications tied into your Discord server, c
- Has a bug in which it does not read passed in variables appropriately to Odin. Env variables are not impacted see [#3].
[//]: <> (Github Issues below...........)
[#276]: https://github.com/mbround18/valheim-docker/pull/276
[#236]: https://github.com/mbround18/valheim-docker/pull/236
[#158]: https://github.com/mbround18/valheim-docker/pull/158
[#148]: https://github.com/mbround18/valheim-docker/pull/148
[#100]: https://github.com/mbround18/valheim-docker/pull/100

View File

@@ -4,10 +4,36 @@
## Steps
1. Download the mod file, for our example we want the `UnixServer.zip` from `https://github.com/nxPublic/ValheimPlus/releases`
2. Place the file in your server volume mount. `cp UnixServer.zip /home/youruser/valheim/server`
3. Unzip the archive `unzip UnixServer.zip -d .` hit A to replace all as needed.
4. Restart your server.
1. Set the variable `TYPE` to be ONne of the following:
| Type | What it installs |
|-------------|------------------|
| Vanilla | Default value and the most common installation type. This will run Valheim normally. |
| BepInEx | This will install [BepInEx from this package](https://valheim.thunderstore.io/package/denikson/BepInExPack_Valheim/) and is purely just BepInEx with minimally needed components. |
| BepInExFull | This will install [BepInEx Full from this package](https://valheim.thunderstore.io/package/1F31A/BepInEx_Valheim_Full/) and contains a modern set of components with some extras for expanded mod compatibility. |
| ValheimPlus | This will install [Valheim Plus from this repository](https://github.com/valheimPlus/ValheimPlus) and included BepInEx as a basic version with the most common set of components |
2. If you wish do not with to use additional mods, you can skip this step. Otherwise, in order to install additional mods you can use the `MODS` variable.
Example of MODS, this example is slimmed down to go over the `TYPE` and `MODS` variable.
```yaml
version: "3"
services:
valheim:
image: mbround18/valheim:latest
environment:
# The Type variable is used to set which type of server you would like to run.
- TYPE=ValheimPlus
# The Mods variable is a comma and newline separated string.
# It MUST be a link with a command and a new line at the end to be valid.
- "MODS=
https://cdn.thunderstore.io/live/repository/packages/abearcodes-SimpleRecycling-0.0.10.zip,
https://cdn.thunderstore.io/live/repository/packages/abearcodes-CraftingWithContainers-1.0.9.zip
"
```
3. Now that you have your compose setup, run `docker-compose up`
> Odin automatically detects if you are running with BepInEx and adds the environment variables appropriately.
>
@@ -20,4 +46,5 @@
## Valheim Updated Help!!!!
Mod development is slow, and the more mods you have the more complicated it will be to keep everything up to date.
It is a suggestion that you turn off the AUTO_UPDATE variable when you are using mods and refrain from updating your local client until all your mods have been updated.
It is a suggestion that you turn off the AUTO_UPDATE variable when you are using mods and refrain from updating your local client until all your mods have been updated.
Some mods break on new updates of Valheim while others do not. Be on the look out for mod issues if you update your server.

View File

@@ -83,6 +83,8 @@ subcommands:
required: true
index: 2
- update:
version: "1.0"
author: LovecraftianHorror
about: >
Attempts to update an existing Valheim server installation. By
default this involves checking for an update, if an update is
@@ -118,3 +120,14 @@ subcommands:
value_name: WEBHOOK_URL
about: Sets the webhook to send a notification to, (Can be set with ENV variable WEBHOOK_URL)
takes_value: true
- mod:install:
about: >
Installs a mod from a given source by downloading the zip file and then extracting it.
Supported platforms are Nexus (with premium account and API key), GitHub, and any other direct download source.
version: "1.0"
author: mbround18
args:
- URL:
about: Url of the mod to download and install
required: true
index: 1

View File

@@ -0,0 +1,18 @@
use crate::mods::ValheimMod;
use clap::ArgMatches;
use log::{debug, error, info};
use std::process::exit;
pub fn invoke(args: &ArgMatches) {
let mut valheim_mod = ValheimMod::new(args.value_of("URL").unwrap());
info!("Installing {}", valheim_mod.url);
debug!("Mod URL: {}", valheim_mod.url);
debug!("Mod staging location: {}", valheim_mod.staging_location);
match valheim_mod.download() {
Ok(_) => valheim_mod.install(),
Err(message) => {
error!("{}", message);
exit(1);
}
};
}

View File

@@ -1,6 +1,7 @@
pub mod backup;
pub mod configure;
pub mod install;
pub mod install_mod;
pub mod notify;
pub mod start;
pub mod stop;

View File

@@ -1,9 +1,18 @@
// Odin Specific
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const ODIN_WORKING_DIR: &str = "ODIN_WORKING_DIR";
pub const SAVE_LOCATION: &str = "SAVE_LOCATION";
pub const MODS_LOCATION: &str = "MODS_LOCATION";
pub const GAME_LOCATION: &str = "GAME_LOCATION";
// pub const BACKUP_LOCATION: &str = "BACKUP_LOCATION";
// Valheim
pub const VALHEIM_EXECUTABLE_NAME: &str = "valheim_server.x86_64";
pub const GAME_ID: i64 = 896660;
pub const VALHEIM_EXECUTABLE_NAME: &str = "valheim_server.x86_64";
// BePinEx
pub const LD_LIBRARY_PATH_VAR: &str = "LD_LIBRARY_PATH";
pub const LD_PRELOAD_VAR: &str = "LD_PRELOAD";
pub const ODIN_WORKING_DIR: &str = "ODIN_WORKING_DIR";
// Mods
pub const SUPPORTED_FILE_TYPES: &[&str] = &["zip", "dll", "cfg"];

View File

@@ -1,4 +1,4 @@
use clap::{load_yaml, App};
use clap::{load_yaml, App, AppSettings};
use log::{debug, info, LevelFilter, SetLoggerError};
use crate::executable::handle_exit_status;
@@ -36,7 +36,9 @@ fn setup_logger(debug: bool) -> Result<(), SetLoggerError> {
fn main() {
// The YAML file is found relative to the current file, similar to how modules are found
let yaml = load_yaml!("cli.yaml");
let app = App::from(yaml).version(constants::VERSION);
let app = App::from(yaml)
.version(constants::VERSION)
.setting(AppSettings::SubcommandRequired);
let matches = app.get_matches();
let debug_mode = matches.is_present("debug") || environment::fetch_var("DEBUG_MODE", "0").eq("1");
setup_logger(debug_mode).unwrap();
@@ -44,38 +46,31 @@ fn main() {
info!("Run with DEBUG_MODE as 1 if you think there is an issue with Odin");
}
debug!("Debug mode enabled!");
if let Some(ref configure_matches) = matches.subcommand_matches("configure") {
debug!("Launching configure command...");
commands::configure::invoke(configure_matches);
if let Some((command_name, _)) = matches.subcommand() {
debug!("Launching {} command...", command_name);
};
if let Some(ref _match) = matches.subcommand_matches("install") {
debug!("Launching install command...");
let result = commands::install::invoke(constants::GAME_ID);
handle_exit_status(result, "Successfully installed Valheim!".to_string())
};
if let Some(ref start_matches) = matches.subcommand_matches("start") {
debug!("Launching start command...");
NotificationEvent::Start(EventStatus::Running).send_notification();
commands::start::invoke(start_matches);
NotificationEvent::Start(EventStatus::Successful).send_notification();
};
if let Some(ref stop_matches) = matches.subcommand_matches("stop") {
debug!("Launching stop command...");
NotificationEvent::Stop(EventStatus::Running).send_notification();
commands::stop::invoke(stop_matches);
NotificationEvent::Stop(EventStatus::Successful).send_notification();
};
if let Some(ref backup_matches) = matches.subcommand_matches("backup") {
debug!("Launching backup command...");
commands::backup::invoke(backup_matches);
};
if let Some(ref notify_matches) = matches.subcommand_matches("notify") {
debug!("Launching notify command...");
commands::notify::invoke(notify_matches);
};
if let Some(ref update_matches) = matches.subcommand_matches("update") {
debug!("Launching update command...");
commands::update::invoke(update_matches);
match matches.subcommand().expect("Subcommand is required") {
("configure", sub_m) => commands::configure::invoke(sub_m),
("install", _) => {
let result = commands::install::invoke(constants::GAME_ID);
handle_exit_status(result, "Successfully installed Valheim!".to_string())
}
("start", sub_m) => {
NotificationEvent::Start(EventStatus::Running).send_notification();
commands::start::invoke(sub_m);
NotificationEvent::Start(EventStatus::Successful).send_notification();
}
("stop", sub_m) => {
NotificationEvent::Stop(EventStatus::Running).send_notification();
commands::stop::invoke(sub_m);
NotificationEvent::Stop(EventStatus::Successful).send_notification();
}
("backup", sub_m) => commands::backup::invoke(sub_m),
("notify", sub_m) => commands::notify::invoke(sub_m),
("update", sub_m) => commands::update::invoke(sub_m),
("mod:install", sub_m) => commands::install_mod::invoke(sub_m),
_ => {
panic!("No Command Launched!");
} // Either no subcommand or one not tested for...
}
}

View File

@@ -7,7 +7,5 @@ pub fn modding_disclaimer() {
info!("By installing mods, you agree that you will do a root cause analysis to why your server is failing before you make a post.");
info!("Modding is currently unsupported by the Valheim developers and limited support by the valheim-docker repo.");
info!("If you have issues please contact the MOD developer FIRST based on the output logs.");
info!("----------------------------------------------------------------");
info!("Additional Note: BepInEx does not support SIGINT shutdown, which means you will have to manually save your world before shutting down.");
info!("##########################################################################################################################");
}

View File

@@ -1,5 +1,6 @@
use crate::constants;
use crate::utils::{environment, get_working_dir, path_exists};
use crate::utils::common_paths::{bepinex_directory, game_directory};
use crate::utils::{environment, path_exists};
use log::{debug, info};
use std::ops::Add;
use std::process::{Child, Command};
@@ -12,29 +13,16 @@ const DOORSTOP_LIBS_VAR: &str = "DOORSTOP_LIBS";
const DOORSTOP_INVOKE_DLL_PATH_VAR: &str = "DOORSTOP_INVOKE_DLL_PATH";
const DOORSTOP_CORLIB_OVERRIDE_PATH_VAR: &str = "DOORSTOP_CORLIB_OVERRIDE_PATH";
fn doorstop_lib() -> String {
environment::fetch_var(DOORSTOP_LIB_VAR, "libdoorstop_x64.so")
}
fn doorstop_libs() -> String {
environment::fetch_var(
DOORSTOP_LIBS_VAR,
format!("{}/doorstop_libs", get_working_dir()).as_str(),
)
}
fn doorstop_insert_lib() -> String {
let default = format!("{}/{}", doorstop_libs(), doorstop_lib().replace(":", ""));
environment::fetch_var(DYLD_INSERT_LIBRARIES_VAR, default.as_str())
}
fn doorstop_invoke_dll() -> String {
environment::fetch_var(
DOORSTOP_INVOKE_DLL_PATH_VAR,
format!("{}/BepInEx/core/BepInEx.Preloader.dll", get_working_dir()).as_str(),
)
fn parse_path(env_var: &str, default: String, alt: String) -> String {
let output = environment::fetch_var(env_var, &default);
if !path_exists(&output) && path_exists(&alt) {
String::from(&alt)
} else {
String::from(&output)
}
}
#[derive(Debug)]
pub struct BepInExEnvironment {
ld_preload: String,
ld_library_path: String,
@@ -45,96 +33,91 @@ pub struct BepInExEnvironment {
dyld_insert_libraries: String,
}
pub fn build_environment() -> BepInExEnvironment {
let ld_preload =
environment::fetch_var(constants::LD_PRELOAD_VAR, "").add(doorstop_lib().as_str());
let ld_library_path = environment::fetch_var(
constants::LD_LIBRARY_PATH_VAR,
format!("./linux64:{}", doorstop_libs()).as_str(),
);
let doorstop_invoke_dll_value = doorstop_invoke_dll();
let doorstop_corlib_override_path = environment::fetch_var(
DOORSTOP_CORLIB_OVERRIDE_PATH_VAR,
format!("{}/{}", get_working_dir(), "unstripped_corlib").as_str(),
);
let dyld_library_path = environment::fetch_var(DYLD_LIBRARY_PATH_VAR, doorstop_libs().as_str());
let dyld_insert_libraries =
environment::fetch_var(DYLD_INSERT_LIBRARIES_VAR, doorstop_insert_lib().as_str());
info!("Checking for BepInEx Environment...");
let environment = BepInExEnvironment {
ld_preload,
ld_library_path,
doorstop_enable: true.to_string().to_uppercase(),
doorstop_invoke_dll: doorstop_invoke_dll_value,
doorstop_corlib_override_path,
dyld_library_path,
dyld_insert_libraries,
};
debug!("LD_PRELOAD: {}", &environment.ld_preload);
debug!("LD_LIBRARY_PATH: {}", &environment.ld_library_path);
debug!("DOORSTOP_ENABLE: {}", &environment.doorstop_enable);
debug!(
"DOORSTOP_INVOKE_DLL_PATH: {}",
&environment.doorstop_invoke_dll
);
debug!(
"{}: {}",
DOORSTOP_CORLIB_OVERRIDE_PATH_VAR, &environment.doorstop_corlib_override_path
);
debug!("DYLD_LIBRARY_PATH: {}", &environment.dyld_library_path);
debug!(
"DYLD_INSERT_LIBRARIES: {}",
&environment.dyld_insert_libraries
);
environment
}
impl BepInExEnvironment {
pub fn new() -> BepInExEnvironment {
let game_dir = game_directory();
let bepinex_dir = bepinex_directory();
let bepinex_preloader_dll = format!("{}/core/BepInEx.Preloader.dll", &bepinex_dir);
pub fn is_bepinex_installed() -> bool {
let bepinex_env: BepInExEnvironment = build_environment();
debug!("Checking for BepInEx specific files...");
let checks = &[
bepinex_env.doorstop_corlib_override_path,
bepinex_env.dyld_insert_libraries,
bepinex_env.dyld_library_path,
bepinex_env.doorstop_invoke_dll,
];
let expected_state = true;
let output = checks.iter().all(|ref v| path_exists(&v) == expected_state);
if output {
debug!("Yay! looks like we found all the required files for BepInEx to run! <3")
} else {
debug!("Uhh ohh!!! Looks like you are missing something.")
}
output
}
pub fn invoke(command: &mut Command, environment: &BepInExEnvironment) -> std::io::Result<Child> {
info!("BepInEx found! Setting up Environment...");
command
// DOORSTOP_ENABLE must not have quotes around it.
.env(DOORSTOP_ENABLE_VAR, &environment.doorstop_enable)
// DOORSTOP_INVOKE_DLL_PATH must not have quotes around it.
.env(
DOORSTOP_INVOKE_DLL_PATH_VAR,
&environment.doorstop_invoke_dll,
)
.env(
debug!("Parsing Doorstop locations.");
let doorstop_lib = environment::fetch_var(DOORSTOP_LIB_VAR, "libdoorstop_x64.so");
let doorstop_libs = parse_path(
DOORSTOP_LIBS_VAR,
format!("{}/doorstop_libs", &game_dir),
format!("{}/doorstop", &bepinex_dir),
);
let doorstop_invoke_dll =
environment::fetch_var(DOORSTOP_INVOKE_DLL_PATH_VAR, &bepinex_preloader_dll);
let doorstop_corlib_override_path = parse_path(
DOORSTOP_CORLIB_OVERRIDE_PATH_VAR,
&environment.doorstop_corlib_override_path,
)
// LD_LIBRARY_PATH must not have quotes around it.
.env(constants::LD_LIBRARY_PATH_VAR, &environment.ld_library_path)
// LD_PRELOAD must not have quotes around it.
.env(constants::LD_PRELOAD_VAR, &environment.ld_preload)
// DYLD_LIBRARY_PATH is weird af and MUST have quotes around it.
.env(
DYLD_LIBRARY_PATH_VAR,
format!("\"{}\"", &environment.dyld_library_path),
)
// DYLD_INSERT_LIBRARIES must not have quotes around it.
.env(
DYLD_INSERT_LIBRARIES_VAR,
&environment.dyld_insert_libraries,
)
.spawn()
format!("{}/unstripped_corlib", &game_dir),
format!("{}/core_lib", &bepinex_dir),
);
let doorstop_base_dll = format!("{}/{}", &doorstop_libs, &doorstop_lib);
debug!("Parsing LD locations.");
let ld_preload = environment::fetch_var(constants::LD_PRELOAD_VAR, "").add(&doorstop_lib);
let ld_library_path = environment::fetch_var(
constants::LD_LIBRARY_PATH_VAR,
format!("./linux64:{}", &doorstop_libs).as_str(),
);
debug!("Parsing LD locations.");
let dyld_library_path = environment::fetch_var(DYLD_LIBRARY_PATH_VAR, &doorstop_libs);
let dyld_insert_libraries =
environment::fetch_var(DYLD_INSERT_LIBRARIES_VAR, &doorstop_base_dll);
debug!("Returning environment");
BepInExEnvironment {
ld_preload,
ld_library_path,
doorstop_enable: true.to_string().to_uppercase(),
doorstop_invoke_dll,
doorstop_corlib_override_path,
dyld_library_path,
dyld_insert_libraries,
}
}
pub fn is_installed(&self) -> bool {
debug!("Checking for BepInEx specific files...");
let checks = &[
&self.doorstop_corlib_override_path,
&self.dyld_insert_libraries,
&self.dyld_library_path,
&self.doorstop_invoke_dll,
];
let expected_state = true;
let output = checks.iter().all(|ref v| path_exists(&v) == expected_state);
if output {
debug!("Yay! looks like we found all the required files for BepInEx to run! <3")
} else {
debug!("Uhh ohh!!! Looks like you are missing something.")
}
output
}
pub fn launch(&self, command: &mut Command) -> std::io::Result<Child> {
info!("BepInEx found! Setting up Environment...");
command
// DOORSTOP_ENABLE must not have quotes around it.
.env(DOORSTOP_ENABLE_VAR, &self.doorstop_enable)
// DOORSTOP_INVOKE_DLL_PATH must not have quotes around it.
.env(DOORSTOP_INVOKE_DLL_PATH_VAR, &self.doorstop_invoke_dll)
.env(
DOORSTOP_CORLIB_OVERRIDE_PATH_VAR,
&self.doorstop_corlib_override_path,
)
// LD_LIBRARY_PATH must not have quotes around it.
.env(constants::LD_LIBRARY_PATH_VAR, &self.ld_library_path)
// LD_PRELOAD must not have quotes around it.
.env(constants::LD_PRELOAD_VAR, &self.ld_preload)
// DYLD_LIBRARY_PATH is weird af and MUST have quotes around it.
.env(
DYLD_LIBRARY_PATH_VAR,
format!("\"{}\"", &self.dyld_library_path),
)
// DYLD_INSERT_LIBRARIES must not have quotes around it.
.env(DYLD_INSERT_LIBRARIES_VAR, &self.dyld_insert_libraries)
.spawn()
}
}

View File

@@ -1 +1,241 @@
pub mod bepinex;
use crate::constants::SUPPORTED_FILE_TYPES;
use crate::utils::common_paths::{
bepinex_config_directory, bepinex_plugin_directory, game_directory,
};
use crate::utils::{common_paths, get_md5_hash, parse_file_name, path_exists, url_parse_file_type};
use fs_extra::dir;
use fs_extra::dir::CopyOptions;
use log::{debug, error, info};
use reqwest::Url;
use serde::{Deserialize, Serialize};
use std::fs::{create_dir_all, File};
use std::path::Path;
use std::process::exit;
use zip::result::ZipError;
use zip::ZipArchive;
pub struct ValheimMod {
pub(crate) url: String,
pub(crate) file_type: String,
pub(crate) staging_location: String,
pub(crate) installed: bool,
pub(crate) downloaded: bool,
pub(crate) staged: bool,
}
#[derive(Serialize, Deserialize)]
struct Manifest {
name: String,
}
impl ValheimMod {
pub fn new(url: &str) -> ValheimMod {
let file_type = url_parse_file_type(url);
ValheimMod {
url: String::from(url),
file_type,
staging_location: common_paths::mods_directory(),
installed: false,
downloaded: false,
staged: false,
}
}
// fn uninstall(&self) {}
fn try_parse_manifest(&self, archive: &mut ZipArchive<File>) -> Result<Manifest, ZipError> {
debug!("Parsing manifest...");
let manifest = archive.by_name("manifest.json")?;
Ok(serde_json::from_reader(manifest).expect("Failed deserializing manifest"))
}
fn copy_staged_plugin(&mut self, manifest: &Manifest) {
if !&self.staged {
error!("Zip file not extracted to staging location!!");
// TODO: Remove Exit Code and provide an Ok or Err.
exit(1);
}
let working_directory = game_directory();
let mut staging_output = String::from(&self.staging_location);
let sub_dir = format!("{}/{}", &staging_output, &manifest.name);
debug!("Manifest suggests sub directory: {}", sub_dir);
let mut dir_copy_options = dir::CopyOptions::new();
dir_copy_options.overwrite = true;
let mut copy_destination = bepinex_plugin_directory();
if path_exists(&sub_dir)
&& (manifest.name.eq("BepInExPack_Valheim") || manifest.name.eq("BepInEx_Valheim_Full"))
{
staging_output = format!("{}/{}", &staging_output, &manifest.name);
copy_destination = String::from(&working_directory);
} else {
copy_destination = format!("{}/{}", &copy_destination, &manifest.name);
debug!("Creating mod directory: {}", &copy_destination);
match create_dir_all(&copy_destination) {
Ok(_) => info!("Created mod directory: {}", &copy_destination),
Err(_) => {
error!("Failed to create mod directory! {}", &copy_destination);
// TODO: Remove Exit Code and provide an Ok or Err.
exit(1);
}
};
}
debug!(
"Copying contents from: \n{}\nInto Directory:\n{}",
&staging_output, &working_directory
);
let source_contents: Vec<_> = std::fs::read_dir(&staging_output)
.unwrap()
.map(|entry| entry.unwrap().path())
.collect();
match fs_extra::copy_items(&source_contents, &copy_destination, &dir_copy_options) {
Ok(_) => info!("Successfully installed {}", &self.url),
Err(_) => {
error!("Failed to install {}", &self.url);
// TODO: Remove Exit Code and provide an Ok or Err.
exit(1);
}
}
}
fn copy_single_file(&self, from: &str, to: String) {
let mut dir_options = CopyOptions::new();
dir_options.overwrite = true;
match fs_extra::copy_items(&[&from], &to, &dir_options) {
Ok(_) => debug!("Successfully copied {} to {}", &from, &to),
Err(_) => {
error!("Failed to install {}", self.url);
error!(
"File failed to copy from: \n{}To Destination:{}",
&from, &to
);
// TODO: Remove Exit Code and provide an Ok or Err.
exit(1);
}
};
}
fn stage_plugin(&mut self, archive: &mut ZipArchive<File>) {
let mut staging_output = String::from(
Path::new(&self.staging_location)
.file_stem()
.unwrap()
.to_str()
.unwrap(),
);
staging_output = format!("{}/{}", common_paths::mods_directory(), &staging_output);
debug!(
"Extracting contents to staging directory: {}",
staging_output
);
archive.extract(&staging_output).unwrap();
self.staging_location = staging_output;
self.staged = true;
}
fn extract_plugin(&self, archive: &mut ZipArchive<File>) {
let output_path = if archive
.file_names()
.any(|file_name| file_name.eq_ignore_ascii_case("winhttp.dll"))
{
info!("Installing BepInEx...");
common_paths::game_directory()
} else {
info!("Installing Mod...");
common_paths::bepinex_plugin_directory()
};
match archive.extract(output_path) {
Ok(_) => info!("Successfully installed {}", &self.url),
Err(msg) => {
error!(
"Failed to install: {}\nDownloaded Archive: {}\n{}",
&self.url,
&self.staging_location,
msg.to_string()
);
// TODO: Remove Exit Code and provide an Ok or Err.
exit(1);
}
};
}
pub fn install(&mut self) {
if Path::new(&self.staging_location).is_dir() {
error!(
"Failed to install mod! Staging location is a directory! {}",
&self.staging_location
);
// TODO: Remove Exit Code and provide an Ok or Err.
exit(1)
}
if self.file_type.eq("dll") {
self.copy_single_file(&self.staging_location, bepinex_plugin_directory());
} else if self.file_type.eq("cfg") {
self.copy_single_file(&self.staging_location, bepinex_config_directory());
} else {
let zip_file = std::fs::File::open(&self.staging_location).unwrap();
let mut archive = match zip::ZipArchive::new(zip_file) {
Ok(file_archive) => {
debug!("Successfully parsed zip file {}", &self.staging_location);
file_archive
}
Err(_) => {
error!("Failed to parse zip file {}", &self.staging_location);
// TODO: Remove Exit Code and provide an Ok or Err.
exit(1);
}
};
match self.try_parse_manifest(&mut archive) {
Ok(manifest) => {
debug!("Manifest has name: {}", manifest.name);
self.stage_plugin(&mut archive);
self.copy_staged_plugin(&manifest);
}
Err(_) => {
self.extract_plugin(&mut archive);
}
}
}
self.installed = true
}
pub fn download(&mut self) -> Result<String, String> {
debug!("Initializing mod download...");
let download_url = &self.url.clone();
if !Path::new(&self.staging_location).exists() {
error!("Failed to download file to staging location!");
return Err(format!(
"Directory does not exist! {}",
&self.staging_location
));
}
if let Ok(parsed_url) = Url::parse(&download_url) {
match reqwest::blocking::get(parsed_url) {
Ok(mut response) => {
let file_type = url_parse_file_type(&self.url);
if !SUPPORTED_FILE_TYPES.contains(&file_type.as_str()) {
debug!("Using url (in case of redirect): {}", &self.url);
self.url = response.url().to_string();
self.file_type = url_parse_file_type(&response.url().to_string())
}
let file_name = parse_file_name(
&Url::parse(&self.url).unwrap(),
format!("{}.{}", get_md5_hash(&download_url), &self.file_type).as_str(),
);
self.staging_location = format!("{}/{}", &self.staging_location, file_name);
debug!("Downloading to: {}", &self.staging_location);
let mut file = File::create(&self.staging_location).unwrap();
response.copy_to(&mut file).expect("Failed saving mod file");
self.downloaded = true;
debug!("Download Complete!: {}", &self.url);
debug!("Download Output: {}", &self.staging_location);
Ok(String::from("Successful"))
}
Err(err) => {
error!("Failed to download mod: {}", download_url);
Err(err.status().unwrap().to_string())
}
}
} else {
Err(format!(
"Failed to download mod with invalid url: {}",
&download_url
))
}
}
}

View File

@@ -12,15 +12,6 @@ line () {
line
log "Valheim Server - $(date)"
log "Starting auto update..."
log "
Port: ${PORT}
Name: ${NAME}
World: ${WORLD}
Public: ${PUBLIC}
Password: (REDACTED)
"
line
cd /home/steam/valheim || exit 1

View File

@@ -11,87 +11,118 @@ ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ >/etc/timezone
# shellcheck disable=SC2039
if [ "${EUID}" -ne 0 ]; then
log "Please run as root"
exit
log "Please run as root"
exit
fi
log() {
PREFIX="[Valheim][root]"
printf "%-16s: %s\n" "${PREFIX}" "$1"
PREFIX="[Valheim][root]"
printf "%-16s: %s\n" "${PREFIX}" "$1"
}
line() {
log "###########################################################################"
log "###########################################################################"
}
check_version() {
file="/home/steam/.version"
sha="$(tail -n+1 $file | head -n1)"
branch="$(tail -n+2 $file | head -n1)"
repository="$(tail -n+3 $file | head -n1)"
github_version="$(curl -s "https://api.github.com/repos/${repository}/branches/${branch//refs\/heads\//}" | jq '.commit.sha')"
if [ -z "$github_version" ] || [ "$github_version" == "null" ]; then
log "You must be in development. Good luck!"
elif [ "${github_version//\"/}" != "${sha//\"/}" ]; then
log "Hey you! It looks like there is an update on $repository for $branch"
log "Please consider running \`docker-compose pull valheim\` or pull the image based on your use case"
fi
file="/home/steam/.version"
sha="$(tail -n+1 $file | head -n1)"
branch="$(tail -n+2 $file | head -n1)"
repository="$(tail -n+3 $file | head -n1)"
github_version="$(curl -s "https://api.github.com/repos/${repository}/branches/${branch//refs\/heads\//}" | jq '.commit.sha')"
if [ -z "$github_version" ] || [ "$github_version" == "null" ]; then
log "You must be in development. Good luck!"
elif [ "${github_version//\"/}" != "${sha//\"/}" ]; then
log "Hey you! It looks like there is an update on $repository for $branch"
log "Please consider running \`docker-compose pull valheim\` or pull the image based on your use case"
fi
}
clean_up() {
echo "Safely shutting down..." >>/home/steam/output.log
if [[ -n $CRON_PID ]]; then
kill $CRON_PID
fi
echo "Safely shutting down..." >>/home/steam/output.log
if [[ -n $CRON_PID ]]; then
kill $CRON_PID
fi
}
trap 'clean_up' INT TERM
setup_cron() {
set -f
CRON_NAME=$1
SCRIPT_PATH="/home/steam/scripts/$2"
CRON_SCHEDULE=$3
CRON_ENV=$4
LOG_LOCATION="/home/steam/valheim/logs/$CRON_NAME.out"
rm $LOG_LOCATION > /dev/null
printf "%s %s /usr/sbin/gosu steam /bin/bash %s >> %s 2>&1" \
"${CRON_SCHEDULE}" \
"DEBUG_MODE=${DEBUG_MODE:-0} ODIN_CONFIG_FILE=${ODIN_CONFIG_FILE} ODIN_WORKING_DIR=${ODIN_WORKING_DIR} WEBHOOK_URL=${WEBHOOK_URL:-""} ${CRON_ENV}" \
"${SCRIPT_PATH}" \
"${LOG_LOCATION}" \
set -f
CRON_NAME=$1
SCRIPT_PATH="/home/steam/scripts/$2"
CRON_SCHEDULE=$3
PRESET_ENV="
DEBUG_MODE=${DEBUG_MODE:=0}
ODIN_CONFIG_FILE=${ODIN_CONFIG_FILE}
ODIN_WORKING_DIR=${ODIN_WORKING_DIR}
WEBHOOK_URL=${WEBHOOK_URL:-""}
AUTO_UPDATE=${AUTO_UPDATE}
AUTO_BACKUP=${AUTO_BACKUP}
AUTO_BACKUP_REMOVE_OLD=${AUTO_BACKUP_REMOVE_OLD}
AUTO_BACKUP_DAYS_TO_LIVE=${AUTO_BACKUP_DAYS_TO_LIVE}
AUTO_BACKUP_ON_UPDATE=${AUTO_BACKUP_ON_UPDATE}
AUTO_BACKUP_ON_SHUTDOWN=${AUTO_BACKUP_ON_SHUTDOWN}
UPDATE_ON_STARTUP=${UPDATE_ON_STARTUP}
SAVE_LOCATION=${SAVE_LOCATION}
MODS_LOCATION=${MODS_LOCATION}
GAME_LOCATION=${GAME_LOCATION}
BACKUP_LOCATION=${BACKUP_LOCATION}
"
CRON_ENV="${PRESET_ENV} ${4}"
CRON_ENV="$(echo "${CRON_ENV}" | tr '\n' " " )"
LOG_LOCATION="/home/steam/valheim/logs/$CRON_NAME.out"
rm $LOG_LOCATION >/dev/null
printf "%s %s /usr/sbin/gosu steam /bin/bash %s >> %s 2>&1" \
"${CRON_SCHEDULE}" \
"${CRON_ENV}" \
"${SCRIPT_PATH}" \
"${LOG_LOCATION}" \
>/etc/cron.d/${CRON_NAME}
echo "" >>/etc/cron.d/${CRON_NAME}
# Give execution rights on the cron job
chmod 0644 /etc/cron.d/${CRON_NAME}
set +f
echo "" >>/etc/cron.d/${CRON_NAME}
# Give execution rights on the cron job
chmod 0644 /etc/cron.d/${CRON_NAME}
set +f
}
setup_filesystem() {
log "Setting up file systems"
STEAM_UID=${PUID:=1000}
STEAM_GID=${PGID:=1000}
mkdir -p /home/steam/valheim
mkdir -p /home/steam/valheim/logs
mkdir -p /home/steam/backups
chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/valheim
mkdir -p /home/steam/scripts
chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/scripts
mkdir -p /home/steam/valheim
cp /home/steam/steamcmd/linux64/steamclient.so /home/steam/valheim
chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/
chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/valheim
log "Setting up file systems"
STEAM_UID=${PUID:=1000}
STEAM_GID=${PGID:=1000}
# Save Files
mkdir -p ${SAVE_LOCATION}
# Mod staging location
mkdir -p ${MODS_LOCATION}
# Backups
mkdir -p ${BACKUP_LOCATION}
# Valheim Server
mkdir -p ${GAME_LOCATION}
mkdir -p ${GAME_LOCATION}/logs
chown -R ${STEAM_UID}:${STEAM_GID} ${GAME_LOCATION}
cp /home/steam/steamcmd/linux64/steamclient.so /home/steam/valheim
# Other
mkdir -p /home/steam/scripts
chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/scripts
chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/
}
check_memory() {
MEMORY=$(($(getconf _PHYS_PAGES) * $(getconf PAGE_SIZE) / (1024 * 1024)))
MESSAGE="Your system has less than 2GB of ram!!\nValheim might not run on your system!!"
if [ $MEMORY -lt 2000 ]; then
line
log "${MESSAGE^^}"
line
line
fi
MEMORY=$(($(getconf _PHYS_PAGES) * $(getconf PAGE_SIZE) / (1024 * 1024)))
MESSAGE="Your system has less than 2GB of ram!!\nValheim might not run on your system!!"
if [ $MEMORY -lt 2000 ]; then
line
log "${MESSAGE^^}"
line
line
fi
}
line
@@ -107,39 +138,37 @@ log "$(usermod -u ${PUID} steam)"
# shellcheck disable=SC2086
log "$(groupmod -g ${PGID} steam)"
# Configure Cron
AUTO_UPDATE="${AUTO_UPDATE:-0}"
AUTO_BACKUP="${AUTO_BACKUP:-0}"
AUTO_UPDATE="${AUTO_UPDATE:=0}"
AUTO_BACKUP="${AUTO_BACKUP:=0}"
if [ "${AUTO_UPDATE}" -eq 1 ]; then
log "Auto Update Enabled..."
log "Auto Update Schedule: ${AUTO_UPDATE_SCHEDULE}"
AUTO_UPDATE_SCHEDULE=$(echo "$AUTO_UPDATE_SCHEDULE" | tr -d '"')
setup_cron \
log "Auto Update Enabled..."
log "Auto Update Schedule: ${AUTO_UPDATE_SCHEDULE}"
AUTO_UPDATE_SCHEDULE=$(echo "$AUTO_UPDATE_SCHEDULE" | tr -d '"')
setup_cron \
"auto-update" \
"auto_update.sh" \
"${AUTO_UPDATE_SCHEDULE}" \
"AUTO_BACKUP_ON_UPDATE=${AUTO_BACKUP_ON_UPDATE:-0}"
"AUTO_BACKUP_ON_UPDATE=${AUTO_BACKUP_ON_UPDATE:=0}"
fi
if [ "${AUTO_BACKUP}" -eq 1 ]; then
log "Auto Backup Enabled..."
log "Auto Backup Schedule: ${AUTO_BACKUP_SCHEDULE}"
AUTO_BACKUP_SCHEDULE=$(echo "$AUTO_BACKUP_SCHEDULE" | tr -d '"')
setup_cron \
"auto-backup" \
"auto_backup.sh" \
"${AUTO_BACKUP_SCHEDULE}" \
log "Auto Backup Enabled..."
log "Auto Backup Schedule: ${AUTO_BACKUP_SCHEDULE}"
AUTO_BACKUP_SCHEDULE=$(echo "$AUTO_BACKUP_SCHEDULE" | tr -d '"')
setup_cron \
"auto-backup" \
"auto_backup.sh" \
"${AUTO_BACKUP_SCHEDULE}" \
"AUTO_BACKUP_REMOVE_OLD=${AUTO_BACKUP_REMOVE_OLD} AUTO_BACKUP_DAYS_TO_LIVE=${AUTO_BACKUP_DAYS_TO_LIVE}"
fi
# Apply cron job
if [ "${AUTO_BACKUP}" -eq 1 ] || [ "${AUTO_UPDATE}" -eq 1 ]; then
cat /etc/cron.d/* | crontab -
/usr/sbin/cron -f &
export CRON_PID=$!
cat /etc/cron.d/* | crontab -
/usr/sbin/cron -f &
export CRON_PID=$!
fi
# Configure filesystem
@@ -149,4 +178,3 @@ setup_filesystem
log "Launching as steam..."
cd /home/steam/valheim || exit 1
exec gosu steam "$@"

View File

@@ -63,6 +63,58 @@ cp /home/steam/steamcmd/linux64/steamclient.so /home/steam/valheim/linux64/
log "Initializing Variables...."
odin configure || exit 1
log "Checking for TYPE flag"
export TYPE="${TYPE:="vanilla"}"
log "Found Type ${TYPE}"
export TYPE="${TYPE,,}"
export GAME_LOCATION="${GAME_LOCATION:="/home/steam/valheim"}"
if [ "${TYPE}" = "vanilla" ] && [ -n "${MODS:=""}" ]; then
log "Mods supplied but you are running with Vanilla!!!"
log "Mods will NOT be installed!."
elif \
# ValheimPlus not yet installed
{ [ "${TYPE}" = "valheimplus" ] && [ ! -d "${GAME_LOCATION}/BepInEx" ] && [ ! -f "${GAME_LOCATION}/BepInEx/plugins/ValheimPlus.dll" ]; } || \
# ValheimPlus with update on startup or force install
{ [ "${TYPE}" = "valheimplus" ] && { [ "${UPDATE_ON_STARTUP:-0}" -eq 1 ] || [ "${FORCE_INSTALL:-0}" -eq 1 ]; } ; }; then
log "Installing ValheimPlus"
VALHEIM_PLUS_URL="$(curl https://api.github.com/repos/valheimPlus/ValheimPlus/releases/latest | jq -r '.assets[] | select(.name=="UnixServer.zip") | .browser_download_url')"
log "Pulling ValheimPlus from ${VALHEIM_PLUS_URL}"
odin mod:install "${VALHEIM_PLUS_URL}"
elif \
# BepInEx not yet installed
{ [ "${TYPE}" = "bepinex" ] && [ ! -d "${GAME_LOCATION}/BepInEx" ] && [ ! -f "${GAME_LOCATION}/BepInEx/core/BepInEx.dll" ]; } || \
# BepInEx with update on startup or force install
{ [ "${TYPE}" = "bepinex" ] && { [ "${UPDATE_ON_STARTUP:-0}" -eq 1 ] || [ "${FORCE_INSTALL:-0}" -eq 1 ]; } ; }; then
log "Installing BepInEx"
BEPINEX_URL="$(curl https://valheim.thunderstore.io/api/experimental/package/denikson/BepInExPack_Valheim/ | jq -r '.latest.download_url')"
log "Pulling BepInEx from ${BEPINEX_URL}"
odin mod:install "${BEPINEX_URL}"
elif \
# BepInEx not yet installed
{ [ "${TYPE}" = "bepinexfull" ] && [ ! -d "${GAME_LOCATION}/BepInEx" ] && [ ! -f "${GAME_LOCATION}/BepInEx/core/BepInEx.dll" ]; } || \
# BepInEx with update on startup or force install
{ [ "${TYPE}" = "bepinexfull" ] && { [ "${UPDATE_ON_STARTUP:-0}" -eq 1 ] || [ "${FORCE_INSTALL:-0}" -eq 1 ]; } ; }; then
log "Installing BepInEx Full"
BEPINEX_URL="$(curl https://valheim.thunderstore.io/api/experimental/package/1F31A/BepInEx_Valheim_Full/ | jq -r '.latest.download_url')"
log "Pulling BepInEx Full from ${BEPINEX_URL}"
odin mod:install "${BEPINEX_URL}"
fi
log "Running with ${TYPE} Valheim <3"
if [ ! "${TYPE}" = "vanilla" ]; then
SAVE_IFS=$IFS # Save current IFS
IFS=$',\n' # Change IFS to new line
# shellcheck disable=SC2206
MODS=(${MODS:=""}) # split to array $names
IFS=$SAVE_IFS # Restore IFS
for mod in "${MODS[@]}"; do
log "Installing Mod ${mod}"
odin mod:install "${mod}"
done
fi
# Setting up script traps
trap 'cleanup' INT TERM

View File

@@ -3,12 +3,13 @@ use log::{debug, info};
use std::{io, process::Child};
use crate::mods::bepinex::BepInExEnvironment;
use crate::utils::common_paths::saves_directory;
use crate::{
constants,
executable::create_execution,
files::{create_file, ValheimArguments},
messages,
mods::bepinex,
utils::{environment, get_working_dir},
};
@@ -24,9 +25,11 @@ pub fn start_daemonized(config: ValheimArguments) -> Result<CommandResult, Daemo
.stdout(stdout)
.stderr(stderr)
.exit_action(|| {
if bepinex::is_bepinex_installed() {
let bepinex_env = BepInExEnvironment::new();
if bepinex_env.is_installed() {
info!("Server has been started with BepInEx! Keep in mind this may cause errors!!");
messages::modding_disclaimer()
messages::modding_disclaimer();
debug!("{:#?}", bepinex_env);
}
info!("Server has been started and Daemonized. It should be online shortly!");
info!("Keep an eye out for 'Game server connected' in the log!");
@@ -58,16 +61,18 @@ pub fn start(config: &ValheimArguments) -> CommandResult {
&config.password.as_str(),
"-public",
&config.public.as_str(),
"-savedir",
&saves_directory(),
])
.env("SteamAppId", environment::fetch_var("APPID", "892970"))
.current_dir(get_working_dir());
info!("Executable: {}", &config.command);
info!("Launching Command...");
if bepinex::is_bepinex_installed() {
let bepinex_env = BepInExEnvironment::new();
if bepinex_env.is_installed() {
info!("BepInEx detected! Switching to run with BepInEx...");
let bepinex_env = bepinex::build_environment();
bepinex::invoke(base_command, &bepinex_env)
debug!("BepInEx Environment: \n{:#?}", bepinex_env);
bepinex_env.launch(base_command)
} else {
info!("Everything looks good! Running normally!");
base_command

34
src/utils/common_paths.rs Normal file
View File

@@ -0,0 +1,34 @@
use crate::constants::{GAME_LOCATION, MODS_LOCATION, SAVE_LOCATION};
use crate::utils::get_working_dir;
use std::env;
pub fn game_directory() -> String {
env::var(GAME_LOCATION).unwrap_or_else(|_| get_working_dir())
}
pub fn bepinex_directory() -> String {
format!("{}/BepInEx", game_directory())
}
pub fn bepinex_plugin_directory() -> String {
format!("{}/plugins", bepinex_directory())
}
pub fn bepinex_config_directory() -> String {
format!("{}/config", bepinex_directory())
}
pub fn mods_directory() -> String {
env::var(MODS_LOCATION).unwrap_or_else(|_| format!("{}/mods", get_working_dir()))
}
// pub fn backup_directory() -> String {
// env::var(BACKUP_LOCATION).unwrap_or_else(|_| format!("{}/backups", get_working_dir()))
// }
pub fn saves_directory() -> String {
env::var(SAVE_LOCATION).unwrap_or_else(|_| match env::var("HOME") {
Ok(dir) => format!("{}/.config/unity3d/IronGate/Valheim", dir),
Err(_) => format!("{}/backups", get_working_dir()),
})
}

View File

@@ -1,3 +1,4 @@
pub mod common_paths;
pub mod environment;
use clap::ArgMatches;
@@ -6,6 +7,7 @@ use std::env;
use std::path::Path;
use crate::constants;
use reqwest::Url;
pub fn get_working_dir() -> String {
environment::fetch_var(
@@ -32,7 +34,7 @@ pub fn get_variable(args: &ArgMatches, name: &str, default: String) -> String {
.to_string()
}
pub(crate) fn path_exists(path: &str) -> bool {
pub fn path_exists(path: &str) -> bool {
let state = Path::new(path).exists();
debug!(
"Path {} {}",
@@ -41,3 +43,34 @@ pub(crate) fn path_exists(path: &str) -> bool {
);
state
}
pub fn parse_file_name(url: &Url, default: &str) -> String {
String::from(
url
.path_segments()
.and_then(|segments| segments.last())
.and_then(|name| if name.is_empty() { None } else { Some(name) })
.unwrap_or(default),
)
}
pub fn get_md5_hash(context: &str) -> String {
format!("{:x}", md5::compute(context.as_bytes()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hash_str() {
assert_eq!(
get_md5_hash("abcdefghijklmnopqrstuvwxyz"),
"c3fcd3d76192e4007dfb496cca67e13b"
);
}
}
pub fn url_parse_file_type(url: &str) -> String {
url.split('.').last().unwrap().to_string()
}