update_bfe.sh 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #!/bin/bash
  2. # LinuxGSM update_bfe.sh module
  3. # Author: Daniel Gibbs
  4. # Contributors: https://linuxgsm.com/contrib
  5. # Website: https://linuxgsm.com
  6. # Description: Handles updating of Battlefront Eternal servers.
  7. moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
  8. fn_update_node_remote() {
  9. # Gets the latest Node.js 24 build and the installed version.
  10. nodeurl="https://nodejs.org/dist/latest-v24.x"
  11. nodeshasums=$(curl -s "${nodeurl}/SHASUMS256.txt")
  12. nodefilename=$(echo "${nodeshasums}" | grep -o "node-v[0-9.]*-linux-${nodearch}.tar.xz" | head -1)
  13. nodeversion=$(echo "${nodefilename}" | cut -d '-' -f 2)
  14. nodehash=$(echo "${nodeshasums}" | grep " ${nodefilename}$" | awk '{print $1}')
  15. if [ -z "${nodefilename}" ] || [ -z "${nodehash}" ]; then
  16. fn_print_failure_nl "Unable to get Node.js build"
  17. fn_script_log_fail "Unable to get Node.js build"
  18. core_exit.sh
  19. fi
  20. nodelocalversion=""
  21. if [ -x "${serverfiles}/node/bin/node" ]; then
  22. nodelocalversion=$("${serverfiles}/node/bin/node" --version 2> /dev/null)
  23. fi
  24. }
  25. fn_update_node_dl() {
  26. # Installs the Node.js runtime the server runs on.
  27. fn_fetch_file "${nodeurl}/${nodefilename}" "" "" "" "${tmpdir}" "${nodefilename}" "nochmodx" "norun" "forcedl" "${nodehash}"
  28. rm -rf "${serverfiles:?}/node.new"
  29. fn_dl_extract "${tmpdir}" "${nodefilename}" "${serverfiles}/node.new" "${nodefilename%.tar.xz}"
  30. rm -rf "${serverfiles:?}/node"
  31. mv "${serverfiles}/node.new" "${serverfiles}/node"
  32. fn_clear_tmp
  33. }
  34. fn_update_node() {
  35. fn_update_node_remote
  36. if [ "${nodelocalversion}" != "${nodeversion}" ]; then
  37. fn_update_node_dl
  38. fi
  39. }
  40. fn_update_node_compare() {
  41. fn_print_dots "Checking for update: nodejs.org"
  42. fn_update_node_remote
  43. if [ "${nodelocalversion}" != "${nodeversion}" ]; then
  44. date '+%s' > "${lockdir:?}/update.lock"
  45. fn_print_ok_nl "Checking for update: nodejs.org"
  46. fn_print "\n"
  47. fn_print_nl "${bold}${underline}Node.js update${default} available"
  48. fn_print_nl "* Local version: ${red}${nodelocalversion:-none}${default}"
  49. fn_print_nl "* Remote version: ${green}${nodeversion}${default}"
  50. fn_print "\n"
  51. fn_script_log_info "Node.js update available"
  52. fn_script_log_info "Local version: ${nodelocalversion:-none}"
  53. fn_script_log_info "Remote version: ${nodeversion}"
  54. previousbuild="Node.js ${nodelocalversion:-none}"
  55. localbuild="Node.js ${nodelocalversion:-none}"
  56. remotebuild="Node.js ${nodeversion}"
  57. if [ "${commandname}" == "UPDATE" ]; then
  58. unset updateonstart
  59. fn_update_apply fn_update_node_dl
  60. localbuild="${remotebuild}"
  61. alert="update"
  62. elif [ "${commandname}" == "CHECK-UPDATE" ]; then
  63. alert="check-update"
  64. fi
  65. alert.sh
  66. else
  67. fn_print_ok_nl "Checking for update: nodejs.org"
  68. fn_print "\n"
  69. fn_print_nl "${bold}${underline}No Node.js update${default} available"
  70. fn_print_nl "* Local version: ${green}${nodelocalversion}${default}"
  71. fn_print_nl "* Remote version: ${green}${nodeversion}${default}"
  72. fn_print "\n"
  73. fn_script_log_info "No Node.js update available"
  74. fn_script_log_info "Local version: ${nodelocalversion}"
  75. fn_script_log_info "Remote version: ${nodeversion}"
  76. fi
  77. }
  78. fn_update_prepare() {
  79. # Prepares the game data from the owned game when the release's tools change.
  80. datakey=$(jq -r '.files[] | select((.path | startswith("resources/tools/")) or (.path | startswith("resources/toolchain/python/"))) | "\(.path) \(.sha256)"' "${serverfiles}/bfe/bfe-tree.json" | LC_ALL=C sort)
  81. datakey=$(printf '%s' "${datakey}" | sha256sum | cut -c 1-32)
  82. if [ -f "${serverfiles}/bfe-data/.lgsm-data-key" ] && [ "$(cat "${serverfiles}/bfe-data/.lgsm-data-key")" == "${datakey}" ]; then
  83. return
  84. fi
  85. if [ ! -d "${serverfiles}/GameData" ]; then
  86. fn_print_failure_nl "Game data not found: ${serverfiles}/GameData"
  87. fn_script_log_fail "Game data not found: ${serverfiles}/GameData"
  88. echo -e "* The Steam account must own STAR WARS Battlefront (Classic, 2004)."
  89. echo -e "* Run ./${selfname} validate to download it."
  90. core_exit.sh
  91. fi
  92. preparelog="${lgsmlogdir}/${selfname}-prepare.log"
  93. echo -e "preparing game data, this can take several minutes"
  94. fn_script_log_info "Preparing game data ${datakey}"
  95. rm -rf "${serverfiles:?}/bfe-data.new"
  96. mkdir -p "${serverfiles}/bfe-data.new"
  97. (
  98. cd "${serverfiles}/bfe/tools" || exit 1
  99. env -i PATH="${serverfiles}/bfe/toolchain/bin:/usr/local/bin:/usr/bin:/bin" HOME="${serverfiles}/bfe-data.new" LANG="C.UTF-8" BFE_GAME_DIR="${serverfiles}" BFE_CONTENT_DIR="${serverfiles}/bfe-data.new" KTX2_ENCODER="off" PYTHONUNBUFFERED="1" PYTHONDONTWRITEBYTECODE="1" PYTHONIOENCODING="utf-8" "${serverfiles}/bfe/toolchain/python/bin/python3" -u prepare.py --core-only --jobs "$(nproc)" > "${preparelog}" 2>&1
  100. )
  101. exitcode=$?
  102. if [ "${exitcode}" -ne 0 ]; then
  103. fn_print_failure_nl "Preparing game data"
  104. fn_script_log_fail "Preparing game data, see ${preparelog}"
  105. tail -n 20 "${preparelog}"
  106. rm -rf "${serverfiles:?}/bfe-data.new"
  107. core_exit.sh
  108. fi
  109. echo "${datakey}" > "${serverfiles}/bfe-data.new/.lgsm-data-key"
  110. rm -rf "${serverfiles:?}/bfe-data"
  111. mv "${serverfiles}/bfe-data.new" "${serverfiles}/bfe-data"
  112. fn_print_ok_nl "Preparing game data"
  113. fn_script_log_pass "Preparing game data"
  114. }
  115. fn_update_dl() {
  116. # Download and extract files to tmpdir.
  117. fn_update_node
  118. fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "${remotebuildhash}"
  119. rm -rf "${serverfiles:?}/bfe"
  120. fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}/bfe"
  121. fn_update_prepare
  122. echo "${remotebuild}" > "${localbuildfile}"
  123. fn_clear_tmp
  124. }
  125. fn_update_localbuild() {
  126. # Gets local build info.
  127. fn_print_dots "Checking local build: ${remotelocation}"
  128. if [ -f "${localbuildfile}" ]; then
  129. localbuild="$(cat "${localbuildfile}")"
  130. fi
  131. if [ -z "${localbuild}" ]; then
  132. fn_print_error "Checking local build: ${remotelocation}: missing local build info"
  133. fn_script_log_error "Missing local build info"
  134. fn_script_log_error "Set localbuild to 0"
  135. localbuild="0"
  136. else
  137. fn_print_ok "Checking local build: ${remotelocation}"
  138. fn_script_log_pass "Checking local build"
  139. fi
  140. }
  141. fn_update_remotebuild() {
  142. # Gets remote build info.
  143. apiurl="https://get.battlefronteternal.com/downloads/latest"
  144. remotebuildresponse=$(curl -s "${apiurl}/SHA256SUMS")
  145. remotebuildfilename=$(echo "${remotebuildresponse}" | grep -o "battlefront-eternal-server_[^ ]*_linux-${archivearch}\.tar\.xz" | head -1)
  146. remotebuildhash=$(echo "${remotebuildresponse}" | grep " ${remotebuildfilename}$" | awk '{print $1}')
  147. remotebuild=$(echo "${remotebuildfilename}" | cut -d '_' -f 2)
  148. remotebuildurl="${apiurl}/${remotebuildfilename}"
  149. if [ "${firstcommandname}" != "INSTALL" ]; then
  150. fn_print_dots "Checking remote build: ${remotelocation}"
  151. # Checks if remotebuild variable has been set.
  152. if [ -z "${remotebuild}" ] || [ -z "${remotebuildhash}" ]; then
  153. fn_print_fail "Checking remote build: ${remotelocation}"
  154. fn_script_log_fail "Checking remote build"
  155. core_exit.sh
  156. else
  157. fn_print_ok "Checking remote build: ${remotelocation}"
  158. fn_script_log_pass "Checking remote build"
  159. fi
  160. else
  161. # Checks if remotebuild variable has been set.
  162. if [ -z "${remotebuild}" ] || [ -z "${remotebuildhash}" ]; then
  163. fn_print_failure "Unable to get remote build"
  164. fn_script_log_fail "Unable to get remote build"
  165. core_exit.sh
  166. fi
  167. fi
  168. }
  169. fn_update_compare() {
  170. fn_print_dots "Checking for update: ${remotelocation}"
  171. # Update has been found or force update.
  172. if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then
  173. # Create update lockfile.
  174. date '+%s' > "${lockdir:?}/update.lock"
  175. fn_print_ok_nl "Checking for update: ${remotelocation}"
  176. fn_print "\n"
  177. fn_print_nl "${bold}${underline}Update${default} available"
  178. fn_print_nl "* Local build: ${red}${localbuild}${default}"
  179. fn_print_nl "* Remote build: ${green}${remotebuild}${default}"
  180. if [ -f "${rootdir}/.dev-debug" ]; then
  181. fn_print_nl "Remote build info"
  182. fn_print_nl "* apiurl: ${apiurl}"
  183. fn_print_nl "* remotebuildfilename: ${remotebuildfilename}"
  184. fn_print_nl "* remotebuildurl: ${remotebuildurl}"
  185. fn_print_nl "* remotebuild: ${remotebuild}"
  186. fi
  187. fn_print "\n"
  188. fn_script_log_info "Update available"
  189. fn_script_log_info "Local build: ${localbuild}"
  190. fn_script_log_info "Remote build: ${remotebuild}"
  191. fn_script_log_info "${localbuild} > ${remotebuild}"
  192. if [ "${commandname}" == "UPDATE" ]; then
  193. unset updateonstart
  194. fn_update_apply fn_update_dl
  195. alert="update"
  196. elif [ "${commandname}" == "CHECK-UPDATE" ]; then
  197. alert="check-update"
  198. fi
  199. alert.sh
  200. else
  201. fn_print_ok_nl "Checking for update: ${remotelocation}"
  202. fn_print "\n"
  203. fn_print_nl "${bold}${underline}No update${default} available"
  204. fn_print_nl "* Local build: ${green}${localbuild}${default}"
  205. fn_print_nl "* Remote build: ${green}${remotebuild}${default}"
  206. fn_print "\n"
  207. fn_script_log_info "No update available"
  208. fn_script_log_info "Local build: ${localbuild}"
  209. fn_script_log_info "Remote build: ${remotebuild}"
  210. if [ -f "${rootdir}/.dev-debug" ]; then
  211. fn_print_nl "Remote build info"
  212. fn_print_nl "* apiurl: ${apiurl}"
  213. fn_print_nl "* remotebuildfilename: ${remotebuildfilename}"
  214. fn_print_nl "* remotebuildurl: ${remotebuildurl}"
  215. fn_print_nl "* remotebuild: ${remotebuild}"
  216. fi
  217. fi
  218. }
  219. if [ "$(uname -m)" == "aarch64" ]; then
  220. archivearch="arm64"
  221. nodearch="arm64"
  222. else
  223. archivearch="amd64"
  224. nodearch="x64"
  225. fi
  226. localbuildfile="${datadir}/${selfname}-bfe-version"
  227. # The location where the builds are checked and downloaded.
  228. remotelocation="get.battlefronteternal.com"
  229. if [ "${firstcommandname}" == "INSTALL" ]; then
  230. fn_update_remotebuild
  231. fn_update_dl
  232. else
  233. fn_print_dots "Checking for update"
  234. fn_print_dots "Checking for update: ${remotelocation}"
  235. fn_script_log_info "Checking for update: ${remotelocation}"
  236. fn_update_localbuild
  237. fn_update_remotebuild
  238. fn_update_compare
  239. if [ "${localbuild}" == "${remotebuild}" ] && [ "${forceupdate}" != "1" ]; then
  240. fn_update_node_compare
  241. fi
  242. fi