diff --git a/.editorconfig b/.editorconfig index fba6f1fb33..51413030f0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -30,3 +30,7 @@ indent_size = 4 [*.py] indent_style = space indent_size = 4 + +# Markdown Files +[*.md] +indent_size = unset diff --git a/.github/linters/.ruff.toml b/.github/linters/.ruff.toml new file mode 100644 index 0000000000..01f243f4bd --- /dev/null +++ b/.github/linters/.ruff.toml @@ -0,0 +1,11 @@ +# Store the cache in a temporary location +cache-dir = "/tmp/.ruff_cache" + +# Same as Black +line-length = 88 + +# Oldest Python on supported distros (Ubuntu 20.04) +target-version = "py38" + +[lint] +ignore = ["E203"] diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d95b4278eb..a666c2f241 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,20 +1,23 @@ # Description -Please include a summary of the change and which issues are fixed. + Fixes #[issue] +Affected servers: + ## Type of change - [ ] Bug fix (a change which fixes an issue). - [ ] New feature (a change which adds functionality). - [ ] New Server (new server added). - [ ] Refactor (restructures existing code). +- [ ] Chore (CI, workflows, tooling or other maintenance). - [ ] Comment update (typo, spelling, explanation, examples, etc). ## Testing -Please list the exact validation you performed and the outcome. + - Commands/tests run: - Result: @@ -30,28 +33,23 @@ Please list the exact validation you performed and the outcome. - [ ] No breaking changes. - [ ] Breaking changes included (describe below). -## Documentation impact +## Documentation + + - [ ] No documentation update required. -- [ ] User documentation update required. -- [ ] Developer documentation update required. +- [ ] User documentation update required ([LinuxGSM-Docs](https://github.com/GameServerManagers/LinuxGSM-Docs)). +- [ ] Developer documentation update required ([LinuxGSM-Dev-Docs](https://github.com/GameServerManagers/LinuxGSM-Dev-Docs)). ## Checklist PR will not be merged until all steps are complete. -- [ ] This pull request links to an issue. +- [ ] This pull request links to an issue ("Fixes", or "Related to" for a partial fix). - [ ] This pull request uses the develop branch as its base. - [ ] This pull request subject follows the Conventional Commits standard. - [ ] This code follows the style guidelines of this project. - [ ] I have performed a self-review of my code. - [ ] I have provided a detailed enough description of this PR. -## Documentation - -If documentation does need updating either update it by creating a PR (preferred) or request a documentation update. - -- User docs: -- Dev docs: - **Thank you for your Pull Request!** diff --git a/.github/scripts/details-check-generate-matrix.sh b/.github/scripts/details-check-generate-matrix.sh index cf37b528c0..9aaa0a18db 100755 --- a/.github/scripts/details-check-generate-matrix.sh +++ b/.github/scripts/details-check-generate-matrix.sh @@ -1,50 +1,50 @@ #!/bin/bash +# Splits the servers to check into shards (one job each) and a list of legacy servers. +# Legacy servers need an older glibc than the hosted runners have, so they run in an ubuntu:20.04 container. +# Writes shards.json (matrix) and legacy.txt (space-separated shortnames). ref="${LGSM_REF:-${GITHUB_REF#refs/heads/}}" -curl "https://raw.githubusercontent.com/GameServerManagers/LinuxGSM/${ref}/lgsm/data/serverlist.csv" | grep -v '^[[:blank:]]*$' > serverlist.csv +maxshards="${DETAILS_CHECK_SHARDS:-12}" +legacyservers="bfv bf1942 btl onset" -echo -n "{" > "shortnamearray.json" -echo -n "\"include\":[" >> "shortnamearray.json" +if [ -f lgsm/data/serverlist.csv ]; then + serverlist="lgsm/data/serverlist.csv" +else + curl -fsS "https://raw.githubusercontent.com/GameServerManagers/LinuxGSM/${ref}/lgsm/data/serverlist.csv" -o serverlist.csv + serverlist="serverlist.csv" +fi -while read -r line; do - shortname=$(echo "$line" | awk -F, '{ print $1 }') - # If TARGETED_SHORTNAMES is set, skip servers not in the list - if [ -n "${TARGETED_SHORTNAMES:-}" ]; then - if ! echo "${TARGETED_SHORTNAMES}" | grep -qw "${shortname}"; then - continue - fi +shortnames=() +legacy=() +while IFS=, read -r shortname _; do + [ -z "${shortname}" ] && continue + if [ -n "${TARGETED_SHORTNAMES:-}" ] && ! echo "${TARGETED_SHORTNAMES}" | grep -qw "${shortname}"; then + continue fi - export shortname - servername=$(echo "$line" | awk -F, '{ print $2 }') - export servername - gamename=$(echo "$line" | awk -F, '{ print $3 }') - export gamename - distro=$(echo "$line" | awk -F, '{ print $4 }') - export distro - # Legacy servers that require older Ubuntu/Debian versions due to glibc compatibility - case "${shortname}" in - bfv | bf1942) - # Requires Ubuntu <= 22.04 or Debian <= 12 (glibc 2.31 compatible) - runner="ubuntu-22.04" - ;; - btl | onset) - # Requires Ubuntu <= 20.04 or Debian <= 11 (glibc 2.31 compatible) - runner="ubuntu-20.04" - ;; - *) - runner="ubuntu-latest" - ;; - esac - { - echo -n "{" - echo -n "\"shortname\":" - echo -n "\"${shortname}\"" - echo -n ",\"runner\":" - echo -n "\"${runner}\"" - echo -n "}," - } >> "shortnamearray.json" -done < <(tail -n +2 serverlist.csv) -sed -i '$ s/.$//' "shortnamearray.json" -echo -n "]" >> "shortnamearray.json" -echo -n "}" >> "shortnamearray.json" -rm serverlist.csv + if echo "${legacyservers}" | grep -qw "${shortname}"; then + legacy+=("${shortname}") + else + shortnames+=("${shortname}") + fi +done < <(tail -n +2 "${serverlist}" | grep -v '^[[:blank:]]*$') + +count="${#shortnames[@]}" +shards=$((count < maxshards ? count : maxshards)) +declare -a shard +for i in "${!shortnames[@]}"; do + shard[i % shards]+="${shortnames[i]} " +done + +{ + echo -n '{"include":[' + for ((i = 0; i < shards; i++)); do + [ "${i}" -gt 0 ] && echo -n ',' + echo -n "{\"shard\":\"$((i + 1))/${shards}\",\"shortnames\":\"${shard[i]% }\"}" + done + echo -n ']}' +} > shards.json + +echo -n "${legacy[*]}" > legacy.txt +[ "${serverlist}" == "serverlist.csv" ] && rm serverlist.csv + +echo "Servers: ${count} in ${shards} shard(s), legacy: ${legacy[*]:-none}" diff --git a/.github/scripts/details-check-run.sh b/.github/scripts/details-check-run.sh new file mode 100755 index 0000000000..5131fc829a --- /dev/null +++ b/.github/scripts/details-check-run.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Runs the details check for each shortname given, in one shared LinuxGSM directory. +# Modules, default configs and data come from the checkout, so the code under test is used and nothing is downloaded per server. +# Usage: details-check-run.sh ... + +src="${GITHUB_WORKSPACE:-${PWD}}" +workdir="${DETAILS_CHECK_DIR:-${HOME}/details-check}" +summary="${GITHUB_STEP_SUMMARY:-/dev/null}" +export LGSM_GITHUBBRANCH="${LGSM_REF:?LGSM_REF must be set}" + +rm -rf "${workdir}" +mkdir -p "${workdir}/lgsm" "${workdir}/serverfiles" +cp "${src}/linuxgsm.sh" "${workdir}/" +cp -r "${src}/lgsm/modules" "${src}/lgsm/config-default" "${src}/lgsm/data" "${workdir}/lgsm/" +cd "${workdir}" || exit 1 + +result() { + if [ "${1}" -eq 0 ]; then echo "✅ pass"; else echo "❌ fail"; fi +} + +failed=() +{ + echo "| Server | Config | Details | Parse game details | Query raw |" + echo "|--------|--------|---------|--------------------|-----------|" +} >> "${summary}" + +for shortname in "$@"; do + gameserver="${shortname}server" + echo "::group::${gameserver}" + ./linuxgsm.sh "${gameserver}" + ./"${gameserver}" developer + + servercfg=$(sed -n "/^\/ { s/.*= *\"\?\([^\"']*\)\"\?/\1/p;q }" "lgsm/config-lgsm/${gameserver}/_default.cfg") + if [ -n "${servercfg}" ]; then + cfgpath="${servercfg}" + [[ "${cfgpath}" == \$\{*\}/* ]] && cfgpath="${cfgpath#*\}/}" + curl -fsS -o "config-${shortname}" "https://raw.githubusercontent.com/GameServerManagers/Game-Server-Configs/main/${shortname}/${cfgpath}" + config=$? + [ "${config}" -eq 0 ] && cat "config-${shortname}" + configresult=$(result "${config}") + else + echo "This game server has no config file." + config=0 + configresult="➖ none" + fi + grep "startparameters" "lgsm/config-default/config-lgsm/${gameserver}/_default.cfg" + + ./"${gameserver}" details + details=$? + ./"${gameserver}" parse-game-details + parse=$? + ./"${gameserver}" query-raw + query=$? + echo "::endgroup::" + + if [ "${config}" -ne 0 ] || [ "${details}" -ne 0 ] || [ "${parse}" -ne 0 ] || [ "${query}" -ne 0 ]; then + failed+=("${gameserver}") + echo "::error title=${gameserver}::config=${config} details=${details} parse-game-details=${parse} query-raw=${query}" + fi + echo "| ${gameserver} | ${configresult} | $(result "${details}") | $(result "${parse}") | $(result "${query}") |" >> "${summary}" +done + +if [ "${#failed[@]}" -gt 0 ]; then + echo -e "\n**Failed:** ${failed[*]}" >> "${summary}" + exit 1 +fi diff --git a/.github/scripts/sync-game-labels.sh b/.github/scripts/sync-game-labels.sh old mode 100644 new mode 100755 diff --git a/.github/workflows/action-add-to-project.yml b/.github/workflows/action-add-to-project.yml index e963362645..69ba24ee69 100644 --- a/.github/workflows/action-add-to-project.yml +++ b/.github/workflows/action-add-to-project.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Add to Project - uses: actions/add-to-project@v1.0.2 + uses: actions/add-to-project@v2.0.0 with: project-url: https://github.com/orgs/GameServerManagers/projects/11 github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} diff --git a/.github/workflows/action-dependabot-automerge.yml b/.github/workflows/action-dependabot-automerge.yml deleted file mode 100644 index 9107d55650..0000000000 --- a/.github/workflows/action-dependabot-automerge.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Dependabot auto-merge - -on: pull_request - -permissions: - contents: write - pull-requests: write - -jobs: - dependabot: - runs-on: ubuntu-latest - if: github.actor == 'dependabot[bot]' - steps: - - name: Fetch dependabot metadata - id: metadata - uses: dependabot/fetch-metadata@v2 - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - - - name: Approve and enable auto-merge for minor/patch updates - if: steps.metadata.outputs.update-type != 'version-update:semver-major' - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr review --approve "$PR_URL" - gh pr merge --auto --squash "$PR_URL" diff --git a/.github/workflows/action-details-check.yml b/.github/workflows/action-details-check.yml index bed3a41ada..f97b028616 100644 --- a/.github/workflows/action-details-check.yml +++ b/.github/workflows/action-details-check.yml @@ -16,18 +16,21 @@ concurrency: group: details-check-${{ github.ref_name }} cancel-in-progress: true +env: + LGSM_REF: ${{ github.event.pull_request.head.sha || github.sha }} + jobs: create-matrix: if: github.repository_owner == 'GameServerManagers' runs-on: ubuntu-latest - env: - LGSM_REF: ${{ github.event.pull_request.head.sha || github.ref_name }} outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} + legacy: ${{ steps.set-matrix.outputs.legacy }} steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: + ref: ${{ env.LGSM_REF }} # Full history so the base branch ref is available for the # `git diff origin/...HEAD` comparison below (a shallow # checkout has no origin/ and the diff fails). @@ -44,7 +47,7 @@ jobs: # Only these modules directly affect what 'details', 'parse-game-details' # and 'query-raw' output. Everything else (install, fix, update, check_*, # data CSVs, game icons, etc.) is irrelevant to this check. - details_core='^(linuxgsm\.sh|lgsm/modules/(info_game|info_messages|command_details|command_dev_parse_game_details|command_dev_query_raw|core_modules)\.sh)$' + details_core='^(linuxgsm\.sh|lgsm/modules/(info_game|info_messages|command_details|command_dev_parse_game_details|command_dev_query_raw|core_modules)\.sh|\.github/workflows/action-details-check\.yml|\.github/scripts/details-check-.*\.sh)$' if echo "$changed" | grep -qE "${details_core}"; then echo "Details-relevant core file changed — using full matrix." echo "mode=full" >> "$GITHUB_OUTPUT" @@ -60,11 +63,11 @@ jobs: else echo "Targeted servers: $shortnames" echo "mode=targeted" >> "$GITHUB_OUTPUT" - printf '%s\n' $shortnames > targeted_shortnames.txt + echo "$shortnames" > targeted_shortnames.txt fi fi - - name: Generate matrix with generate-matrix.sh + - name: Generate matrix if: github.event_name != 'pull_request' || steps.targeted.outputs.mode != 'skip' run: | if [ -f targeted_shortnames.txt ]; then @@ -76,106 +79,70 @@ jobs: - name: Set Matrix id: set-matrix run: | - if [ ! -f shortnamearray.json ]; then + if [ ! -f shards.json ]; then echo 'matrix={"include":[]}' >> "$GITHUB_OUTPUT" + echo 'legacy=' >> "$GITHUB_OUTPUT" else - shortnamearray=$(cat shortnamearray.json) - echo "${shortnamearray}" - echo -n "matrix=${shortnamearray}" >> "$GITHUB_OUTPUT" + cat shards.json + echo "matrix=$(cat shards.json)" >> "$GITHUB_OUTPUT" + echo "legacy=$(cat legacy.txt)" >> "$GITHUB_OUTPUT" fi details-check: - if: github.repository_owner == 'GameServerManagers' + name: details-check (${{ matrix.shard }}) + # Skip (rather than fail the run) when create-matrix found nothing to check. + if: github.repository_owner == 'GameServerManagers' && needs.create-matrix.outputs.matrix != '{"include":[]}' needs: create-matrix continue-on-error: true - runs-on: ${{ matrix.runner }} - env: - LGSM_REF: ${{ github.event.pull_request.head.sha || github.ref_name }} - + runs-on: ubuntu-latest strategy: + fail-fast: false matrix: ${{ fromJSON(needs.create-matrix.outputs.matrix) }} - steps: - - name: Download linuxgsm.sh - run: wget "https://raw.githubusercontent.com/GameServerManagers/LinuxGSM/${LGSM_REF}/linuxgsm.sh"; chmod +x linuxgsm.sh + - name: Checkout + uses: actions/checkout@v7 + with: + ref: ${{ env.LGSM_REF }} - name: Cache apt packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: /var/cache/apt/archives key: apt-${{ runner.os }}-libxml2-utils-jq - name: Install dependencies - run: sudo apt-get install -y --no-install-recommends libxml2-utils jq - - - name: Create serverfiles directory - run: mkdir -p serverfiles - - - name: Grab server - run: LGSM_GITHUBBRANCH="${LGSM_REF}" ./linuxgsm.sh ${{ matrix.shortname }}server - - - name: Enable developer mode - run: LGSM_GITHUBBRANCH="${LGSM_REF}" ./${{ matrix.shortname }}server developer - - - name: Generate servercfgname - id: sets-servercfgname - run: | - servercfg=$(sed -n "/^\/ { s/.*= *\"\?\([^\"']*\)\"\?/\1/p;q }" lgsm/config-lgsm/${{ matrix.shortname }}server/_default.cfg) - echo "servercfgname=$servercfg" >> "$GITHUB_OUTPUT" - - - name: Download config - run: | - if [ "${{ steps.sets-servercfgname.outputs.servercfgname }}" == "" ]; then - echo "This game server has no config file." - else - curl -f -o config "https://raw.githubusercontent.com/GameServerManagers/Game-Server-Configs/main/${{ matrix.shortname }}/${{ steps.sets-servercfgname.outputs.servercfgname }}" - fi + run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libxml2-utils jq - - name: Pre-load LinuxGSM - run: LGSM_GITHUBBRANCH="${LGSM_REF}" ./${{ matrix.shortname }}server details + - name: Details check + run: .github/scripts/details-check-run.sh ${{ matrix.shortnames }} - - name: Display config + details-check-legacy: + name: details-check (legacy) + if: github.repository_owner == 'GameServerManagers' && needs.create-matrix.outputs.legacy != '' + needs: create-matrix + continue-on-error: true + runs-on: ubuntu-latest + container: public.ecr.aws/ubuntu/ubuntu:20.04 + steps: + - name: Install dependencies + env: + DEBIAN_FRONTEND: noninteractive run: | - if [ "${{ steps.sets-servercfgname.outputs.servercfgname }}" == "" ]; then - echo "This game server has no config file." - else - cat config - fi - - - name: Display parameters - run: grep "startparameters" lgsm/config-default/config-lgsm/${{ matrix.shortname }}server/_default.cfg - - - name: Details - id: details - run: LGSM_GITHUBBRANCH="${LGSM_REF}" ./${{ matrix.shortname }}server details + apt-get update + apt-get install -y --no-install-recommends ca-certificates curl wget git sudo iproute2 libxml2-utils jq \ + bc binutils bsdmainutils bzip2 cpio distro-info file gzip hostname lib32gcc-s1 lib32stdc++6 \ + netcat-openbsd pigz python3 tar tmux unzip util-linux uuid-runtime xz-utils - - name: Detect details - id: detect-details - run: LGSM_GITHUBBRANCH="${LGSM_REF}" ./${{ matrix.shortname }}server parse-game-details - - - name: Query Raw - id: query-raw - run: LGSM_GITHUBBRANCH="${LGSM_REF}" ./${{ matrix.shortname }}server query-raw + - name: Checkout + uses: actions/checkout@v7 + with: + ref: ${{ env.LGSM_REF }} - - name: Write job summary - if: always() + - name: Details check run: | - status_icon() { - case "$1" in - success) echo "✅" ;; - failure) echo "❌" ;; - skipped) echo "⏭️" ;; - *) echo "⚠️" ;; - esac - } - details_icon=$(status_icon "${{ steps.details.outcome }}") - parse_icon=$(status_icon "${{ steps.detect-details.outcome }}") - query_icon=$(status_icon "${{ steps.query-raw.outcome }}") - { - echo "## ${{ matrix.shortname }}server" - echo "| Step | Result |" - echo "|------|--------|" - echo "| Details | ${details_icon} ${{ steps.details.outcome }} |" - echo "| Parse game details | ${parse_icon} ${{ steps.detect-details.outcome }} |" - echo "| Query raw | ${query_icon} ${{ steps.query-raw.outcome }} |" - } >> "$GITHUB_STEP_SUMMARY" + useradd -m linuxgsm + echo "linuxgsm ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/linuxgsm + chown -R linuxgsm:linuxgsm "${GITHUB_WORKSPACE}" + chmod a+w "${GITHUB_STEP_SUMMARY}" + sudo -u linuxgsm -H env LGSM_REF="${LGSM_REF}" GITHUB_WORKSPACE="${GITHUB_WORKSPACE}" GITHUB_STEP_SUMMARY="${GITHUB_STEP_SUMMARY}" \ + "${GITHUB_WORKSPACE}/.github/scripts/details-check-run.sh" ${{ needs.create-matrix.outputs.legacy }} diff --git a/.github/workflows/action-issue-close-fields.yml b/.github/workflows/action-issue-close-fields.yml new file mode 100644 index 0000000000..dfab412298 --- /dev/null +++ b/.github/workflows/action-issue-close-fields.yml @@ -0,0 +1,199 @@ +name: Issue Close Fields +on: + issues: + types: + - closed + workflow_run: + workflows: + - Release Issues + types: + - completed + # checkov:skip=CKV_GHA_7:Inputs only select which closed issues a backfill run touches; nothing is built. + workflow_dispatch: + inputs: + dry_run: + description: List the changes without writing them + required: true + default: "true" + type: choice + options: + - "true" + - "false" + closed_since: + description: Only issues closed on or after this date (YYYY-MM-DD, blank = all) + required: false + default: "" + type: string + limit: + description: Max issues to change (0 = no limit) + required: true + default: "200" + type: string + +permissions: + issues: write + pull-requests: read + contents: read + +concurrency: + group: issue-close-fields-${{ github.event.issue.number || github.run_id }} + +jobs: + issue-close-fields: + if: github.repository_owner == 'GameServerManagers' && (github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success') + runs-on: ubuntu-latest + steps: + - name: Fill assignee, outcome, type and milestone on closed issues + uses: actions/github-script@v9 + env: + DEFAULT_ASSIGNEE: dgibbs64 + DRY_RUN: ${{ inputs.dry_run || 'false' }} + CLOSED_SINCE: ${{ inputs.closed_since }} + LIMIT: ${{ inputs.limit || '0' }} + with: + script: | + const { owner, repo } = context.repo; + const dryRun = process.env.DRY_RUN === 'true'; + const limit = Number.parseInt(process.env.LIMIT || '0', 10) || 0; + const outcomeByReason = { + completed: 'outcome: issue resolved', + duplicate: 'outcome: duplicate', + }; + const issueTypeByLabel = { + 'type: bug': 'Bug', + 'type: feature': 'Feature', + 'type: game server request': 'Server Request', + 'type: docs': 'Task', + }; + + let milestoneByTitle = null; + let releases = null; + async function loadReleaseData() { + if (releases) return; + const milestones = await github.paginate(github.rest.issues.listMilestones, { owner, repo, state: 'all', per_page: 100 }); + milestoneByTitle = new Map(milestones.map((m) => [m.title, m])); + releases = (await github.paginate(github.rest.repos.listReleases, { owner, repo, per_page: 100 })) + .filter((r) => !r.draft && !r.prerelease && r.published_at) + .sort((a, b) => new Date(a.published_at) - new Date(b.published_at)); + } + + async function releaseMilestoneFor(sha, mergedAt) { + await loadReleaseData(); + for (const release of releases) { + if (new Date(release.published_at) < new Date(mergedAt)) continue; + const { data } = await github.rest.repos.compareCommits({ owner, repo, base: release.tag_name, head: sha, per_page: 1 }); + if (data.status !== 'behind' && data.status !== 'identical') continue; + const minor = release.tag_name.match(/^v(\d+)\.(\d+)\./); + return milestoneByTitle.get(release.tag_name) || (minor && milestoneByTitle.get(`v${minor[1]}.${minor[2]}.0`)) || null; + } + return null; + } + + async function milestoneFor(issueNumber) { + const data = await github.graphql( + `query($owner:String!,$repo:String!,$number:Int!){ + repository(owner:$owner,name:$repo){ + issue(number:$number){ + closedByPullRequestsReferences(first:10,includeClosedPrs:true){ + nodes { number merged mergedAt mergeCommit { oid } milestone { number title } } + } + } + } + }`, + { owner, repo, number: issueNumber } + ); + const prs = (data.repository?.issue?.closedByPullRequestsReferences?.nodes || []) + .filter((pr) => pr.merged && pr.mergeCommit?.oid) + .sort((a, b) => new Date(a.mergedAt) - new Date(b.mergedAt)); + if (prs.length === 0) return null; + const chosen = prs.find((pr) => pr.milestone); + if (chosen) return { number: chosen.milestone.number, title: chosen.milestone.title, source: `#${chosen.number}` }; + const released = await releaseMilestoneFor(prs[0].mergeCommit.oid, prs[0].mergedAt); + return released ? { number: released.number, title: released.title, source: `#${prs[0].number} release` } : null; + } + + async function planChanges(issue) { + const labels = (issue.labels || []).map((l) => (typeof l === 'string' ? l : l.name)); + const changes = {}; + if ((issue.assignees || []).length === 0) changes.assignee = process.env.DEFAULT_ASSIGNEE; + const outcome = outcomeByReason[issue.state_reason]; + if (outcome && !labels.some((l) => l.startsWith('outcome: '))) changes.label = outcome; + const typeLabel = labels.find((l) => issueTypeByLabel[l]); + if (!issue.type && typeLabel) changes.type = issueTypeByLabel[typeLabel]; + if (issue.state_reason === 'completed' && !issue.milestone) { + const milestone = await milestoneFor(issue.number); + if (milestone) changes.milestone = milestone; + } + return changes; + } + + async function applyChanges(issueNumber, changes) { + if (changes.assignee) { + await github.rest.issues.addAssignees({ owner, repo, issue_number: issueNumber, assignees: [changes.assignee] }); + } + if (changes.label) { + await github.rest.issues.addLabels({ owner, repo, issue_number: issueNumber, labels: [changes.label] }); + } + const update = {}; + if (changes.type) update.type = changes.type; + if (changes.milestone) update.milestone = changes.milestone.number; + if (Object.keys(update).length > 0) { + await github.rest.issues.update({ owner, repo, issue_number: issueNumber, ...update }); + } + } + + function describe(changes) { + const parts = []; + if (changes.assignee) parts.push(`assignee ${changes.assignee}`); + if (changes.label) parts.push(`label "${changes.label}"`); + if (changes.type) parts.push(`type ${changes.type}`); + if (changes.milestone) parts.push(`milestone ${changes.milestone.title} (from ${changes.milestone.source})`); + return parts.join(', '); + } + + let issues; + if (context.eventName === 'issues') { + issues = [context.payload.issue]; + } else { + const sinceInput = context.eventName === 'workflow_run' + ? new Date(Date.now() - 2 * 24 * 60 * 60 * 1000) + : (process.env.CLOSED_SINCE ? new Date(`${process.env.CLOSED_SINCE}T00:00:00Z`) : null); + const listParams = { owner, repo, state: 'closed', sort: 'updated', direction: 'desc', per_page: 100 }; + if (sinceInput) listParams.since = sinceInput.toISOString(); + issues = (await github.paginate(github.rest.issues.listForRepo, listParams)) + .filter((issue) => !issue.pull_request) + .filter((issue) => !sinceInput || new Date(issue.closed_at) >= sinceInput) + .sort((a, b) => new Date(b.closed_at) - new Date(a.closed_at)); + } + + const rows = []; + const failures = []; + let changed = 0; + for (const issue of issues) { + if (limit > 0 && changed >= limit) break; + try { + const changes = await planChanges(issue); + if (Object.keys(changes).length === 0) continue; + if (!dryRun) await applyChanges(issue.number, changes); + changed += 1; + rows.push([`#${issue.number}`, issue.state_reason || '', describe(changes)]); + core.info(`${dryRun ? 'Would set' : 'Set'} #${issue.number}: ${describe(changes)}`); + } catch (err) { + failures.push(`#${issue.number}: ${err.message}`); + core.warning(`#${issue.number}: ${err.message}`); + if (err.status === 403 || err.status === 429) { + core.warning('Rate limited, stopping. Re-run to continue: done issues are skipped.'); + break; + } + } + } + + await core.summary + .addHeading(`Issue close fields (${dryRun ? 'dry run' : 'applied'})`) + .addRaw(`Checked ${issues.length} closed issue(s), ${changed} needed changes.\n\n`) + .addTable([ + [{ data: 'Issue', header: true }, { data: 'Close reason', header: true }, { data: 'Changes', header: true }], + ...rows, + ]) + .addRaw(failures.length > 0 ? `\nFailures:\n\n${failures.map((f) => `- ${f}`).join('\n')}\n` : '') + .write(); diff --git a/.github/workflows/action-issue-triage-automation.yml b/.github/workflows/action-issue-triage-automation.yml index 4992613c48..70282cbd74 100644 --- a/.github/workflows/action-issue-triage-automation.yml +++ b/.github/workflows/action-issue-triage-automation.yml @@ -43,7 +43,9 @@ on: - created - edited - deleted - pull_request: + # pull_request_target so pr-labeler can label PRs from forks (pull_request gets a read-only token for forks). + # Safe here: no job checks out or runs PR code on this event. + pull_request_target: types: - opened - edited @@ -67,11 +69,11 @@ env: jobs: issue-regex-labeler: - if: github.repository_owner == 'GameServerManagers' && github.event_name == 'issues' && (github.event.action == 'opened' || github.event.action == 'edited') + if: github.repository_owner == 'GameServerManagers' && github.event_name == 'issues' && github.event.issue.state == 'open' && (github.event.action == 'opened' || github.event.action == 'edited') runs-on: ubuntu-latest steps: - name: Issue Labeler - uses: github/issue-labeler@v3.4 + uses: github/issue-labeler@v3.5 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" configuration-path: .github/labeler.yml @@ -80,7 +82,7 @@ jobs: sync-labels: 0 issue-ai-maintenance: - if: github.repository_owner == 'GameServerManagers' && (github.event_name == 'issues' || github.event_name == 'issue_comment') + if: github.repository_owner == 'GameServerManagers' && (github.event_name == 'issues' || github.event_name == 'issue_comment') && github.event.issue.state == 'open' runs-on: ubuntu-latest steps: - name: Reconcile issue labels and AI triage @@ -234,6 +236,38 @@ jobs: return false; } + function parseVdf(text) { + const root = {}; + const stack = [root]; + let pendingKey = null; + const tokenPattern = /"((?:[^"\\]|\\.)*)"|([{}])/g; + let match; + while ((match = tokenPattern.exec(text)) !== null) { + const current = stack[stack.length - 1]; + if (match[2] === '{') { + const child = {}; + if (pendingKey !== null) current[pendingKey] = child; + stack.push(child); + pendingKey = null; + } else if (match[2] === '}') { + if (stack.length > 1) stack.pop(); + pendingKey = null; + } else if (pendingKey === null) { + pendingKey = match[1]; + } else { + current[pendingKey] = match[1]; + pendingKey = null; + } + } + return root; + } + + function parseSteamAppInfo(output, appId) { + const start = output.search(new RegExp(`^"${appId}"\\s*$`, 'm')); + if (start === -1) return null; + return parseVdf(output.slice(start))[String(appId)] ?? null; + } + function runSteamCmdLinuxCheck(appId) { if (!appId) { return { status: 'skipped', reason: 'No Steam AppID provided.' }; @@ -269,23 +303,44 @@ jobs: maxBuffer: 10 * 1024 * 1024, }); - const normalized = output.toLowerCase(); - const linuxSignals = [ - /"oslist"\s+"linux"/i, - /"oslist"\s+"linux,windows"/i, - /"oslist"\s+"windows,linux"/i, - /"platforms"[\s\S]*?"linux"\s+"1"/i, - /linux32/i, - /linux64/i, - ]; - const windowsOnlySignals = [ - /"oslist"\s+"windows"/i, - /"platforms"[\s\S]*?"windows"\s+"1"/i, - ]; - - const hasLinuxSignal = linuxSignals.some((re) => re.test(normalized)); + const appInfo = parseSteamAppInfo(output, appId); + if (!appInfo) { + return { + status: 'unknown', + reason: `SteamCMD app_info returned no data for AppID ${appId}.`, + }; + } + + const osListOf = (node) => String(node?.config?.oslist ?? '').toLowerCase(); + const isObject = (value) => value && typeof value === 'object'; + const commonOsList = String(appInfo.common?.oslist ?? '').toLowerCase(); + const launches = Object.values(appInfo.config?.launch ?? {}).filter(isObject); + const serverDepots = Object.entries(appInfo.depots ?? {}).filter( + ([id, depot]) => + /^\d+$/.test(id) && + isObject(depot) && + !['1004', '1005', '1006'].includes(id) && + depot.depotfromapp === undefined && + depot.sharedinstall !== '1' + ); + + const hasLinuxSignal = + commonOsList.includes('linux') || + launches.some( + (launch) => + osListOf(launch).includes('linux') || + (!osListOf(launch) && /\.(sh|x86_64)$/i.test(launch.executable ?? '')) + ) || + serverDepots.some(([, depot]) => osListOf(depot).includes('linux')); const hasWindowsOnlySignal = - !hasLinuxSignal && windowsOnlySignals.some((re) => re.test(normalized)); + !hasLinuxSignal && + (commonOsList === 'windows' || + (launches.length > 0 && + launches.every( + (launch) => + osListOf(launch) === 'windows' || + /\.(exe|bat|cmd)$/i.test(launch.executable ?? '') + ))); if (hasLinuxSignal) { return { @@ -764,8 +819,37 @@ jobs: } // Avoid pointless API calls. - const finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label)); - const finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label)); + let finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label)); + let finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label)); + + const isGameOrEngineLabel = (label) => label.startsWith('game: ') || label.startsWith('engine: '); + if ([...finalAdds, ...finalRemoves].some(isGameOrEngineLabel)) { + try { + const issueEvents = await github.paginate(github.rest.issues.listEvents, { + owner, + repo, + issue_number: issueNumber, + per_page: 100, + }); + const lastManualLabelEvent = new Map(); + for (const e of issueEvents) { + if (!['labeled', 'unlabeled'].includes(e.event) || !e.label?.name) continue; + lastManualLabelEvent.set(e.label.name, e.actor?.type === 'Bot' ? null : e.event); + } + finalAdds = finalAdds.filter((label) => { + if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'unlabeled') return true; + console.log(`Label "${label}" was removed manually; not adding it back.`); + return false; + }); + finalRemoves = finalRemoves.filter((label) => { + if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'labeled') return true; + console.log(`Label "${label}" was added manually; keeping it.`); + return false; + }); + } catch (err) { + console.log(`Could not read issue events: ${err.message}`); + } + } for (const label of finalRemoves) { try { @@ -1008,8 +1092,36 @@ jobs: const CONFIRMED_LINUX_LABEL = 'status: linux support confirmed'; const LINUX_MARKER = ''; const steamDbLink = steamAppId ? `https://steamdb.info/app/${steamAppId}/` : null; - const shouldApplyNoLinuxLabel = confirmedNoLinux || suggestsNoLinux; - const shouldApplyConfirmedLinuxLabel = confirmedLinuxSupport && !confirmedNoLinux && !suggestsNoLinux; + + let linuxLabelOverrideBy = null; + try { + const issueEvents = await github.paginate(github.rest.issues.listEvents, { + owner, + repo, + issue_number: issueNumber, + per_page: 100, + }); + const lastLinuxLabelEvent = issueEvents + .filter( + (e) => + ['labeled', 'unlabeled'].includes(e.event) && + [NO_LINUX_LABEL, CONFIRMED_LINUX_LABEL].includes(e.label?.name) + ) + .at(-1); + if (lastLinuxLabelEvent && lastLinuxLabelEvent.actor?.type !== 'Bot') { + linuxLabelOverrideBy = lastLinuxLabelEvent.actor?.login ?? 'a maintainer'; + console.log(`Linux support label last set by ${linuxLabelOverrideBy}; keeping it.`); + } + } catch (err) { + console.log(`Could not read issue events: ${err.message}`); + } + + const shouldApplyNoLinuxLabel = linuxLabelOverrideBy + ? existingLabels.has(NO_LINUX_LABEL) + : confirmedNoLinux || suggestsNoLinux; + const shouldApplyConfirmedLinuxLabel = linuxLabelOverrideBy + ? existingLabels.has(CONFIRMED_LINUX_LABEL) && !existingLabels.has(NO_LINUX_LABEL) + : confirmedLinuxSupport && !confirmedNoLinux && !suggestsNoLinux; if (shouldApplyNoLinuxLabel) { // Auto-create the label if it does not exist yet. @@ -1105,7 +1217,11 @@ jobs: if (likelySupportedByCheckbox) reasons.push('requester confirmed Linux support via the form checkbox; no contradicting evidence found'); let verdictLine = 'Linux support could not be confirmed automatically from the submitted details.'; - if (confirmedNoLinux) { + if (linuxLabelOverrideBy && shouldApplyNoLinuxLabel) { + verdictLine = 'A maintainer has confirmed this server has no native Linux support.'; + } else if (linuxLabelOverrideBy && shouldApplyConfirmedLinuxLabel) { + verdictLine = 'A maintainer has confirmed native Linux support.'; + } else if (confirmedNoLinux) { verdictLine = 'This server request does **not** appear to have native Linux support, which is required for LinuxGSM.'; } else if (suggestsNoLinux) { verdictLine = 'This server request **may not** have native Linux support based on submitted evidence.'; @@ -1160,9 +1276,14 @@ jobs: ? `**Label applied:** ${CONFIRMED_LINUX_LABEL}\n\n` : ''; + const overrideBlock = linuxLabelOverrideBy + ? `**Maintainer override:** the Linux support label was set manually by @${linuxLabelOverrideBy} and is no longer changed automatically.\n\n` + : ''; + const linuxCommentBody = `${LINUX_MARKER}\n` + `${linuxCommentHeader}\n\n` + + `${overrideBlock}` + `${verdictLine}\n\n` + `${confirmedLinuxLabelBlock}` + `${steamBlock}` + @@ -2107,8 +2228,38 @@ jobs: } // Apply changes - const finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label)); - const finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label)); + let finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label)); + let finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label)); + + const isGameOrEngineLabel = (label) => label.startsWith('game: ') || label.startsWith('engine: '); + if ([...finalAdds, ...finalRemoves].some(isGameOrEngineLabel)) { + try { + const issueEvents = await github.paginate(github.rest.issues.listEvents, { + owner, + repo, + issue_number: rawIssue.number, + per_page: 100, + }); + const lastManualLabelEvent = new Map(); + for (const e of issueEvents) { + if (!['labeled', 'unlabeled'].includes(e.event) || !e.label?.name) continue; + lastManualLabelEvent.set(e.label.name, e.actor?.type === 'Bot' ? null : e.event); + } + finalAdds = finalAdds.filter((label) => { + if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'unlabeled') return true; + console.log(`#${rawIssue.number}: "${label}" was removed manually; not adding it back`); + return false; + }); + finalRemoves = finalRemoves.filter((label) => { + if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'labeled') return true; + console.log(`#${rawIssue.number}: "${label}" was added manually; keeping it`); + return false; + }); + } catch (err) { + if (isApiRateLimitError(err)) throw err; + console.log(`#${rawIssue.number}: could not read issue events: ${err.message}`); + } + } let labelAdded = 0; let labelRemoved = 0; @@ -2267,11 +2418,15 @@ jobs: } pr-labeler: - if: github.repository_owner == 'GameServerManagers' && github.event_name == 'pull_request' + if: github.repository_owner == 'GameServerManagers' && github.event_name == 'pull_request_target' runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write steps: - name: PR Labeler - uses: github/issue-labeler@v3.4 + uses: github/issue-labeler@v3.5 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" configuration-path: .github/labeler.yml @@ -2294,7 +2449,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v7 - name: Sync game labels from serverlist env: diff --git a/.github/workflows/action-milestone-sync.yml b/.github/workflows/action-milestone-sync.yml new file mode 100755 index 0000000000..e0891094ad --- /dev/null +++ b/.github/workflows/action-milestone-sync.yml @@ -0,0 +1,78 @@ +name: Milestone Sync +on: + pull_request_target: + types: + - opened + - reopened + - ready_for_review + - edited + - milestoned + - closed + branches: + - develop + +permissions: + issues: write + pull-requests: write + +concurrency: + group: milestone-sync-${{ github.event.pull_request.number }} + +jobs: + milestone-sync: + if: github.repository_owner == 'GameServerManagers' + runs-on: ubuntu-latest + steps: + - name: Sync selected milestone to linked issues + uses: actions/github-script@v9 + with: + script: | + const { owner, repo } = context.repo; + const pr = context.payload.pull_request; + const action = context.payload.action; + const fixedLabel = 'status: fixed in develop'; + + if (action === 'closed' && !pr.merged) { + return; + } + + const milestone = pr.milestone; + + const body = (pr.body || '').replace(//g, ''); + const issueRef = /\b(close[sd]?|fix(?:e[sd])?|resolve[sd]?|related to):?\s+(?:([\w.-]+)\/([\w.-]+))?#(\d+)/gi; + const issues = new Map(); + for (const m of body.matchAll(issueRef)) { + if (m[2] && (m[2].toLowerCase() !== owner.toLowerCase() || m[3].toLowerCase() !== repo.toLowerCase())) { + continue; + } + const number = Number(m[4]); + const closing = !/^related to$/i.test(m[1]); + issues.set(number, issues.get(number) || closing); + } + + for (const [number, closing] of issues) { + let issue; + try { + ({ data: issue } = await github.rest.issues.get({ owner, repo, issue_number: number })); + } catch (error) { + core.warning(`Could not read #${number}: ${error.message}`); + continue; + } + if (issue.pull_request) { + continue; + } + + if (milestone && issue.milestone?.number !== milestone.number) { + if (issue.milestone && !pr.merged) { + core.info(`#${number} is in ${issue.milestone.title}; it will move to ${milestone.title} when this PR merges.`); + } else { + await github.rest.issues.update({ owner, repo, issue_number: number, milestone: milestone.number }); + core.info(`Set #${number} milestone to ${milestone.title}.`); + } + } + + if (pr.merged && closing && issue.state === 'open' && !issue.labels.some((l) => (l.name || l) === fixedLabel)) { + await github.rest.issues.addLabels({ owner, repo, issue_number: number, labels: [fixedLabel] }); + core.info(`Labelled #${number} "${fixedLabel}".`); + } + } diff --git a/.github/workflows/action-pr-body-check.yml b/.github/workflows/action-pr-body-check.yml new file mode 100755 index 0000000000..bb4475b015 --- /dev/null +++ b/.github/workflows/action-pr-body-check.yml @@ -0,0 +1,83 @@ +name: PR Body Check +on: + pull_request: + types: + - opened + - edited + - reopened + - synchronize + branches: + - develop + +permissions: + contents: read + issues: read + pull-requests: read + +jobs: + pr-body-check: + if: github.repository_owner == 'GameServerManagers' && github.event.pull_request.user.type != 'Bot' && !startsWith(github.event.pull_request.head.ref, 'repo-sync/') + runs-on: ubuntu-latest + steps: + - name: Check pull request body follows the template + uses: actions/github-script@v9 + with: + script: | + const body = (context.payload.pull_request.body || '').replace(//g, ''); + const requiredHeadings = ['# Description', '## Type of change', '## Testing', '## Checklist']; + const missing = requiredHeadings.filter((h) => !body.split(/\r?\n/).some((line) => line.trim() === h)); + const errors = []; + + if (missing.length > 0) { + errors.push(`Missing template sections: ${missing.join(', ')}. Use .github/pull_request_template.md as the pull request body.`); + } + if (/^\s*fixes #\[issue\]\s*$/im.test(body)) { + errors.push('Replace the "Fixes #[issue]" placeholder with the issue number, for example "Fixes #123".'); + } + + const closingKeyword = /\b(close[sd]?|fix(e[sd])?|resolve[sd]?):?\s+([\w.-]+\/[\w.-]+)?#\d+/i; + const relatedIssue = /\brelated to:?\s+([\w.-]+\/[\w.-]+)?#\d+/i; + if (!closingKeyword.test(body) && !relatedIssue.test(body)) { + core.warning('No closing keyword found. Add "Fixes #123" to link the issue, or "Related to #123" if this pull request does not fully resolve it.'); + } + + const repoName = `${context.repo.owner}/${context.repo.repo}`.toLowerCase(); + const closingRefs = [...body.matchAll(/\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?):?\s+([\w.-]+\/[\w.-]+)?#(\d+)/gi)] + .filter((m) => !m[1] || m[1].toLowerCase() === repoName) + .map((m) => Number(m[2])); + const wanted = [...new Set(closingRefs)]; + if (wanted.length > 0) { + const vars = { owner: context.repo.owner, repo: context.repo.repo }; + const { repository } = await github.graphql( + `query($owner: String!, $repo: String!, $number: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number: $number) { closingIssuesReferences(first: 50) { nodes { number } } } + } + }`, + { ...vars, number: context.payload.pull_request.number } + ); + const linked = new Set(repository.pullRequest.closingIssuesReferences.nodes.map((n) => n.number)); + const unlinked = []; + for (const number of wanted.filter((n) => !linked.has(n))) { + try { + const { repository: ref } = await github.graphql( + `query($owner: String!, $repo: String!, $number: Int!) { + repository(owner: $owner, name: $repo) { issueOrPullRequest(number: $number) { __typename } } + }`, + { ...vars, number } + ); + if (ref.issueOrPullRequest?.__typename === 'Issue') { + unlinked.push(`#${number}`); + } + } catch (error) { + core.warning(`Could not look up #${number}: ${error.message}`); + } + } + if (unlinked.length > 0) { + errors.push(`Not linked in Development: ${unlinked.join(', ')}. Closing keywords in pull requests to develop do not link issues. Select each issue in the Development section of this pull request's sidebar, then re-run this check.`); + } + } + + if (errors.length > 0) { + core.setFailed(errors.join('\n')); + } diff --git a/.github/workflows/action-prettier.yml b/.github/workflows/action-prettier.yml index f5d51a44ae..49fbf6ac31 100644 --- a/.github/workflows/action-prettier.yml +++ b/.github/workflows/action-prettier.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: persist-credentials: false diff --git a/.github/workflows/action-release-issues.yml b/.github/workflows/action-release-issues.yml new file mode 100755 index 0000000000..b491f998d8 --- /dev/null +++ b/.github/workflows/action-release-issues.yml @@ -0,0 +1,65 @@ +name: Release Issues +on: + pull_request_target: + types: + - opened + - reopened + - synchronize + - ready_for_review + - closed + branches: + - master + +permissions: + issues: write + pull-requests: write + +concurrency: + group: release-issues-${{ github.event.pull_request.number }} + +jobs: + release-issues: + if: github.repository_owner == 'GameServerManagers' && startsWith(github.event.pull_request.head.ref, 'release/') && github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + steps: + - name: List fixed issues in the release PR and close them on merge + uses: actions/github-script@v9 + with: + script: | + const { owner, repo } = context.repo; + const pr = context.payload.pull_request; + const fixedLabel = 'status: fixed in develop'; + const start = ''; + const end = ''; + + const labelled = (await github.paginate(github.rest.issues.listForRepo, { owner, repo, state: 'all', labels: fixedLabel, per_page: 100 })) + .filter((issue) => !issue.pull_request) + .sort((a, b) => a.number - b.number); + + if (context.payload.action === 'closed') { + if (!pr.merged) { + return; + } + const version = pr.head.ref.replace(/^release\//, ''); + for (const issue of labelled) { + if (issue.state === 'open') { + await github.rest.issues.createComment({ owner, repo, issue_number: issue.number, body: `Released in ${version} (#${pr.number}).` }); + await github.rest.issues.update({ owner, repo, issue_number: issue.number, state: 'closed', state_reason: 'completed' }); + core.info(`Closed #${issue.number}.`); + } + await github.rest.issues.removeLabel({ owner, repo, issue_number: issue.number, name: fixedLabel }).catch(() => {}); + } + return; + } + + const open = labelled.filter((issue) => issue.state === 'open'); + const lines = open.length > 0 ? open.map((issue) => `Fixes #${issue.number}`) : [`No open issues are labelled "${fixedLabel}".`]; + const block = [start, '## Issues fixed in this release', '', ...lines, end].join('\n'); + + const current = pr.body || ''; + const pattern = new RegExp(`${start}[\\s\\S]*?${end}`); + const updated = pattern.test(current) ? current.replace(pattern, block) : `${current.trim() ? `${current.trimEnd()}\n\n` : ''}${block}\n`; + if (updated !== current) { + await github.rest.pulls.update({ owner, repo, pull_number: pr.number, body: updated }); + core.info(`Listed ${open.length} issue(s) in #${pr.number}.`); + } diff --git a/.github/workflows/action-serverlist-validate.yml b/.github/workflows/action-serverlist-validate.yml index 3e88074071..33da083857 100644 --- a/.github/workflows/action-serverlist-validate.yml +++ b/.github/workflows/action-serverlist-validate.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Compare Versions run: .github/scripts/serverlist-validate.sh diff --git a/.github/workflows/action-super-linter.yml b/.github/workflows/action-super-linter.yml index 31b2fa9497..567db5f327 100644 --- a/.github/workflows/action-super-linter.yml +++ b/.github/workflows/action-super-linter.yml @@ -4,10 +4,13 @@ on: workflow_dispatch: push: branches: - - "*" + - main + - master + - develop + pull_request: concurrency: - group: super-linter-${{ github.ref }} + group: super-linter-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: {} @@ -25,7 +28,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: # super-linter needs the full git history to get the # list of files that changed across commits @@ -37,10 +40,12 @@ jobs: npm install --no-save prettier prettier-plugin-sh prettier-plugin-jinja-template || true - name: Super-linter - uses: super-linter/super-linter@v8 + uses: super-linter/super-linter/slim@v9 env: # To report GitHub Actions status checks GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MULTI_STATUS: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} + VALIDATE_ALL_CODEBASE: ${{ github.event_name != 'pull_request' }} VALIDATE_BIOME_FORMAT: false VALIDATE_BIOME_LINT: false VALIDATE_GITHUB_ACTIONS_ZIZMOR: false diff --git a/.github/workflows/action-update-check.yml b/.github/workflows/action-update-check.yml index ad1150f7bd..45cefe3f88 100644 --- a/.github/workflows/action-update-check.yml +++ b/.github/workflows/action-update-check.yml @@ -22,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - shortname: [css, fctr, jk2, mc, mcb, mta, pmc, ts3, ut99, vints, xnt] + shortname: [css, fctr, jk2, mc, mcb, mta, orar, pmc, ts3, ut99, vints, xnt] steps: - name: Download linuxgsm.sh @@ -31,6 +31,13 @@ jobs: - name: Install dependencies run: sudo dpkg --add-architecture i386; sudo apt-get update; + - name: Install Java 25 + if: matrix.shortname == 'mc' || matrix.shortname == 'pmc' + run: | + sudo apt-get install -y openjdk-25-jre + sudo update-alternatives --set java /usr/lib/jvm/java-25-openjdk-amd64/bin/java + java -version + - name: Grab server run: LGSM_GITHUBBRANCH="${LGSM_REF}" ./linuxgsm.sh ${{ matrix.shortname }}server diff --git a/.github/workflows/action-update-copyright-years-in-license-file.yml b/.github/workflows/action-update-copyright-years-in-license-file.yml index ab1549f0e6..7ad5a76dd7 100644 --- a/.github/workflows/action-update-copyright-years-in-license-file.yml +++ b/.github/workflows/action-update-copyright-years-in-license-file.yml @@ -7,13 +7,14 @@ on: permissions: contents: write + pull-requests: write jobs: update-license-year: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 persist-credentials: false @@ -22,8 +23,3 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} path: LICENSE.md - - name: Merge pull request - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr merge --merge --delete-branch diff --git a/.github/workflows/action-version-check.yml b/.github/workflows/action-version-check.yml index 0726295a43..a41edb16c0 100644 --- a/.github/workflows/action-version-check.yml +++ b/.github/workflows/action-version-check.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Version Check run: .github/scripts/version-check.sh diff --git a/.github/workflows/ai-triage.yml b/.github/workflows/ai-triage.yml index fba1e4cf1e..178cfe3b13 100644 --- a/.github/workflows/ai-triage.yml +++ b/.github/workflows/ai-triage.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Triage issue with GitHub Models - uses: actions/github-script@v7 + uses: actions/github-script@v9 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/sync-game-labels.yml b/.github/workflows/sync-game-labels.yml index eccb0ed467..ed7d66c954 100644 --- a/.github/workflows/sync-game-labels.yml +++ b/.github/workflows/sync-game-labels.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v7 - name: Sync game labels from serverlist env: diff --git a/LICENSE.md b/LICENSE.md index c138f40712..c58e808eb2 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -19,3 +19,9 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +## Third-party assets + +The following files are not covered by the MIT License above and remain under their own licenses. + +- `lgsm/data/gameicons/luanti-icon.png`: Luanti icon by erle, licensed under [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/). Copied without modification from [Luanti 5.17.0](https://github.com/luanti-org/luanti/blob/5.17.0/misc/luanti-icon-24x24.png); see the [upstream license and attribution](https://github.com/luanti-org/luanti/blob/5.17.0/LICENSE.txt). diff --git a/lgsm/config-default/config-lgsm/acserver/_default.cfg b/lgsm/config-default/config-lgsm/acserver/_default.cfg index 7ccebf181b..015f989d67 100644 --- a/lgsm/config-default/config-lgsm/acserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/acserver/_default.cfg @@ -15,6 +15,10 @@ steampass='password' ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-c ${servercfgfullpath}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,15 @@ telegramthreadid="" telegramsilentnotification="false" curlcustomstring="" +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/ahl2server/_default.cfg b/lgsm/config-default/config-lgsm/ahl2server/_default.cfg index b955c4180d..289a7a2f39 100644 --- a/lgsm/config-default/config-lgsm/ahl2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/ahl2server/_default.cfg @@ -23,6 +23,10 @@ maxplayers="20" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game ahl2 -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -111,6 +115,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -119,6 +128,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/ahlserver/_default.cfg b/lgsm/config-default/config-lgsm/ahlserver/_default.cfg index 6854d55cfc..9766bcd1af 100644 --- a/lgsm/config-default/config-lgsm/ahlserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/ahlserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game action -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers} " +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" @@ -136,7 +150,7 @@ appid="90" steamcmdforcewindows="no" appidmod="cstrike" # SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch -branch="" +branch="steam_legacy" betapassword="" # Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server steammaster="true" diff --git a/lgsm/config-default/config-lgsm/arkserver/_default.cfg b/lgsm/config-default/config-lgsm/arkserver/_default.cfg index cc492f7b56..1c2bf36a29 100644 --- a/lgsm/config-default/config-lgsm/arkserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/arkserver/_default.cfg @@ -20,6 +20,10 @@ altsavedirectoryname="${defaultmap}" ## Game Server Docs | https://ark.wiki.gg/wiki/Server_configuration startparameters="${defaultmap}?AltSaveDirectoryName=${altsavedirectoryname} -MultiHome=${ip} -Port=${port} -QueryPort=${queryport} -AutoManagedMods -Crossplay -PublicIPForEpic=${publicip}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -108,6 +112,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/arma3server/_default.cfg b/lgsm/config-default/config-lgsm/arma3server/_default.cfg index 46a98ed463..989874843d 100644 --- a/lgsm/config-default/config-lgsm/arma3server/_default.cfg +++ b/lgsm/config-default/config-lgsm/arma3server/_default.cfg @@ -27,6 +27,13 @@ mods="" ## Server-side Mods servermods="" +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to serverfiles/workshop and added to -mod= in the order listed. +# Run ./arma3server workshop-update after changing, or let update apply it. +# workshopmods="450814997" +workshopmods="" + ## Path to BattlEye # Leave empty for default bepath="" @@ -34,6 +41,10 @@ bepath="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-ip=${ip} -port=${port} -cfg=${networkcfgfullpath} -config=${servercfgfullpath} -mod=${mods} -servermod=${servermods} -bepath=${bepath} -autoinit -loadmissiontomemory" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -122,6 +133,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/armarserver/_default.cfg b/lgsm/config-default/config-lgsm/armarserver/_default.cfg index a6532146ff..add29e732e 100644 --- a/lgsm/config-default/config-lgsm/armarserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/armarserver/_default.cfg @@ -19,6 +19,10 @@ serverprofilefullpath="${serverfiles}/profiles/${serverprofile}" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-config ${servercfgfullpath} -profile ${serverprofilefullpath} -maxFPS ${maxfps}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/atsserver/_default.cfg b/lgsm/config-default/config-lgsm/atsserver/_default.cfg index 6b4b0807b1..307cf9d858 100644 --- a/lgsm/config-default/config-lgsm/atsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/atsserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-nosingle" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/avserver/_default.cfg b/lgsm/config-default/config-lgsm/avserver/_default.cfg index 5668c8be3f..1905581b08 100644 --- a/lgsm/config-default/config-lgsm/avserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/avserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="--galaxy-name ${selfname} --ip ${ip} --datapath ${avdatapath}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/bb2server/_default.cfg b/lgsm/config-default/config-lgsm/bb2server/_default.cfg index ec113ed99f..0cac42cd8e 100644 --- a/lgsm/config-default/config-lgsm/bb2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/bb2server/_default.cfg @@ -24,6 +24,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game brainbread2 -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +sv_setsteamaccount ${gslt} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -112,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -120,6 +129,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/bbserver/_default.cfg b/lgsm/config-default/config-lgsm/bbserver/_default.cfg index b3d7b75135..720ed8307c 100644 --- a/lgsm/config-default/config-lgsm/bbserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/bbserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game brainbread -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/bdserver/_default.cfg b/lgsm/config-default/config-lgsm/bdserver/_default.cfg index 5144fd2586..c567bf6f25 100644 --- a/lgsm/config-default/config-lgsm/bdserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/bdserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="3" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game bdef -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/bf1942server/_default.cfg b/lgsm/config-default/config-lgsm/bf1942server/_default.cfg index 86363ccc53..d89d8922e8 100644 --- a/lgsm/config-default/config-lgsm/bf1942server/_default.cfg +++ b/lgsm/config-default/config-lgsm/bf1942server/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+hostServer 1 +dedicated 1" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/bfeserver/_default.cfg b/lgsm/config-default/config-lgsm/bfeserver/_default.cfg new file mode 100644 index 0000000000..7e167bbfb8 --- /dev/null +++ b/lgsm/config-default/config-lgsm/bfeserver/_default.cfg @@ -0,0 +1,224 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +## SteamCMD Login | https://docs.linuxgsm.com/steamcmd#steamcmd-login +# The Steam account must own STAR WARS Battlefront (Classic, 2004). +# Battlefront Eternal prepares its game data from this copy. +steamuser="username" +steampass='password' + +## Health Port +# Local health and admin endpoint. Each instance needs its own. +healthport="18450" + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +## Game Server Docs | https://battlefronteternal.com/servers/ +# Server name, port, max players and playlist are set in config.json. +startparameters="${serverfiles}/bfe/host-runtime/server/src/main.js --serve" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Matrix Alerts | https://docs.linuxgsm.com/alerts/matrix +matrixalert="off" +matrixhomeserver="matrix.org" +matrixtoken="accesstoken" +matrixroom="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="5" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd +# Server appid +appid="1058020" +steamcmdforcewindows="yes" +# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch +branch="" +betapassword="" +# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server +steammaster="false" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +# 12: shutdown +# 13: soulmask +# 14: Running With Rifles +stopmode="2" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="5" +querytype="" + +## Console type +consoleverbose="yes" +consoleinteract="no" + +## Game Server Details +# Do not edit +gamename="Battlefront Eternal" +engine="bfe" +glibc="2.28" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}" +executabledir="${serverfiles}/node/bin" +executable="./node" +servercfgdir="${systemdir}/bfe-state" +servercfg="config.json" +servercfgdefault="config.json" +servercfgfullpath="${servercfgdir}/${servercfg}" +preexecutable="env BFE_STATE_DIR=${servercfgdir} BFE_ENGINE_DIR=${systemdir}/bfe/host-runtime/engine BFE_DATA_DIR=${systemdir}/bfe-data PORT=${healthport}" + +## Backup Directory +backupdir="${lgsmdir}/backup" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/bfvserver/_default.cfg b/lgsm/config-default/config-lgsm/bfvserver/_default.cfg index 7fcfdd5ace..760f3051e7 100644 --- a/lgsm/config-default/config-lgsm/bfvserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/bfvserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+statusMonitor 1" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/bmdmserver/_default.cfg b/lgsm/config-default/config-lgsm/bmdmserver/_default.cfg index 3bcdd5cb95..395429efb8 100644 --- a/lgsm/config-default/config-lgsm/bmdmserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/bmdmserver/_default.cfg @@ -24,6 +24,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game bms -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +sv_setsteamaccount ${gslt} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -112,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -120,6 +129,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/boserver/_default.cfg b/lgsm/config-default/config-lgsm/boserver/_default.cfg index 9d3110ccad..b1d6f96a36 100644 --- a/lgsm/config-default/config-lgsm/boserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/boserver/_default.cfg @@ -16,6 +16,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-batchmode -nographics -dedicated -configfile=${servercfgfullpath}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +108,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/bsserver/_default.cfg b/lgsm/config-default/config-lgsm/bsserver/_default.cfg index 3ef7574a0e..b1aa971ae0 100644 --- a/lgsm/config-default/config-lgsm/bsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/bsserver/_default.cfg @@ -28,6 +28,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game "${serverfiles}/berimbau" -autoupdate -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +sv_setsteamaccount ${gslt} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -116,6 +120,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -124,6 +133,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/btlserver/_default.cfg b/lgsm/config-default/config-lgsm/btlserver/_default.cfg index 7e936b1f77..8424637498 100644 --- a/lgsm/config-default/config-lgsm/btlserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/btlserver/_default.cfg @@ -16,6 +16,10 @@ queryport="7780" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-Port=${port} -QueryPort=${queryport} -BroadcastIp=${publicip} -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +108,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/btserver/_default.cfg b/lgsm/config-default/config-lgsm/btserver/_default.cfg index 0134772b3a..5b29357396 100644 --- a/lgsm/config-default/config-lgsm/btserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/btserver/_default.cfg @@ -11,6 +11,16 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to LocalMods and enabled in config_player.xml. Run ./btserver workshop-update after changing, or let update apply it. +# workshopmods="3815618949" +workshopmods="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/ccserver/_default.cfg b/lgsm/config-default/config-lgsm/ccserver/_default.cfg index 86eaa9d155..2e9616a2b5 100644 --- a/lgsm/config-default/config-lgsm/ccserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/ccserver/_default.cfg @@ -19,6 +19,10 @@ maxplayers="6" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game cure -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +124,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/ceserver/_default.cfg b/lgsm/config-default/config-lgsm/ceserver/_default.cfg new file mode 100644 index 0000000000..64c89d845c --- /dev/null +++ b/lgsm/config-default/config-lgsm/ceserver/_default.cfg @@ -0,0 +1,220 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters +ip="0.0.0.0" +port="7777" +queryport="27015" +servername="LinuxGSM" +maxplayers="40" + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +startparameters="ConanSandbox -log -MULTIHOME=${ip} -Port=${port} -QueryPort=${queryport} -ServerName='${servername}' -MaxPlayers=${maxplayers}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Matrix Alerts | https://docs.linuxgsm.com/alerts/matrix +matrixalert="off" +matrixhomeserver="matrix.org" +matrixtoken="accesstoken" +matrixroom="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="5" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd +# Server appid +appid="443030" +steamcmdforcewindows="no" +# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch +branch="" +betapassword="" +# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server +steammaster="true" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +# 12: shutdown +# 13: soulmask +# 14: Running With Rifles +# 15: Rising World +# 16: Conan Exiles +stopmode="16" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="2" +querytype="protocol-valve" + +## Console type +consoleverbose="yes" +consoleinteract="no" + +## Game Server Details +# Do not edit +gamename="Conan Exiles" +engine="unreal5" +glibc="2.28" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}/ConanSandbox" +executabledir="${systemdir}/Binaries/Linux" +executable="./ConanSandboxServer-Linux-Shipping" +servercfgdir="${systemdir}/Saved/Config/LinuxServer" +servercfg="ServerSettings.ini" +servercfgfullpath="${servercfgdir}/${servercfg}" + +## Backup Directory +backupdir="${lgsmdir}/backup" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +gamelogdir="${systemdir}/Saved/Logs" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/ckserver/_default.cfg b/lgsm/config-default/config-lgsm/ckserver/_default.cfg index b238c21480..8ed388435c 100644 --- a/lgsm/config-default/config-lgsm/ckserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/ckserver/_default.cfg @@ -15,6 +15,10 @@ port="1234" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-batchmode -ip ${ip} -port ${port} -datapath ${servercfgdir} -logfile ${gamelog}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -103,6 +107,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -176,7 +185,7 @@ glibc="2.15" ## Game Server Directories systemdir="${serverfiles}" executabledir="${serverfiles}" -preexecutable="xvfb-run" +preexecutable="xvfb-run -a" executable="./CoreKeeperServer" servercfgdir="${systemdir}/gamedata/${selfname}" servercfg="ServerConfig.json" diff --git a/lgsm/config-default/config-lgsm/cmwserver/_default.cfg b/lgsm/config-default/config-lgsm/cmwserver/_default.cfg index 110013f89a..77e68f9483 100644 --- a/lgsm/config-default/config-lgsm/cmwserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/cmwserver/_default.cfg @@ -17,6 +17,10 @@ defaultmap="AOCTD-Frigid_p" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="${defaultmap}?steamsockets -multihome=${ip} -Port=${port} -QueryPort=${queryport} -seekfreeloadingserver -configsubdir=${selfname} -log=${gamelog}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/cod2server/_default.cfg b/lgsm/config-default/config-lgsm/cod2server/_default.cfg index 45abeb251a..f5943b7144 100644 --- a/lgsm/config-default/config-lgsm/cod2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/cod2server/_default.cfg @@ -17,6 +17,10 @@ maxplayers="20" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set dedicated 2 +set net_ip ${ip} +set net_port ${port} +set sv_maxclients ${maxplayers} +map ${defaultmap} +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -151,7 +160,7 @@ querytype="protocol-quake3" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/cod4server/_default.cfg b/lgsm/config-default/config-lgsm/cod4server/_default.cfg index 0d007db4e5..45df4fc4f9 100644 --- a/lgsm/config-default/config-lgsm/cod4server/_default.cfg +++ b/lgsm/config-default/config-lgsm/cod4server/_default.cfg @@ -17,6 +17,10 @@ maxplayers="32" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set fs_homepath ${serverfiles} +set sv_authorizemode "-1" +set dedicated 2 +set net_ip ${ip} +set net_port ${port} +set sv_maxclients ${maxplayers} +map ${defaultmap} +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -151,7 +160,7 @@ querytype="protocol-quake3" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/codserver/_default.cfg b/lgsm/config-default/config-lgsm/codserver/_default.cfg index de3fc8c237..a31139ab0c 100644 --- a/lgsm/config-default/config-lgsm/codserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/codserver/_default.cfg @@ -17,6 +17,10 @@ maxplayers="20" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set dedicated 2 +set net_ip ${ip} +set net_port ${port} +set sv_maxclients ${maxplayers} +map ${defaultmap} +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -151,7 +160,7 @@ querytype="protocol-quake3" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/coduoserver/_default.cfg b/lgsm/config-default/config-lgsm/coduoserver/_default.cfg index 2e52c6b244..102c557609 100644 --- a/lgsm/config-default/config-lgsm/coduoserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/coduoserver/_default.cfg @@ -17,6 +17,10 @@ maxplayers="20" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set dedicated 2 +set net_ip ${ip} +set net_port ${port} +set sv_maxclients ${maxplayers} +map ${defaultmap} +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -151,7 +160,7 @@ querytype="protocol-quake3" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/codwawserver/_default.cfg b/lgsm/config-default/config-lgsm/codwawserver/_default.cfg index 438c1b785b..7836ea3e9f 100644 --- a/lgsm/config-default/config-lgsm/codwawserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/codwawserver/_default.cfg @@ -17,6 +17,10 @@ maxplayers="20" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set dedicated 2 +set net_ip ${ip} +set net_port ${port} +set sv_maxclients ${maxplayers} +map ${defaultmap} +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -151,7 +160,7 @@ querytype="protocol-quake3" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/colserver/_default.cfg b/lgsm/config-default/config-lgsm/colserver/_default.cfg index 82cf3de7b5..025090d7f0 100644 --- a/lgsm/config-default/config-lgsm/colserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/colserver/_default.cfg @@ -8,10 +8,26 @@ #### Game Server Settings #### +## SteamCMD Login | https://docs.linuxgsm.com/steamcmd#steamcmd-login +# Only needed for Workshop mods. The account must own Colony Survival. +steamuser="" +steampass='' + ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters ## https://colonysurvival.gamepedia.com/Dedicated_Server#Installation_.28Linux.29 startparameters="-batchmode -nographics +server.config ${servercfgfullpath}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Needs steamuser to own Colony Survival. Installed to gamedata/mods and enabled in each world's worldconfig.json. +# Run ./colserver workshop-update after changing, or let update apply it. +# workshopmods="3816302400" +workshopmods="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -100,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -154,7 +175,7 @@ stopmode="2" # 3: gamedig # 4: gsquery # 5: tcp -querymode="2" +querymode="5" querytype="protocol-valve" ## Console type diff --git a/lgsm/config-default/config-lgsm/cs2server/_default.cfg b/lgsm/config-default/config-lgsm/cs2server/_default.cfg index 81d1cb7edb..dff480c13b 100644 --- a/lgsm/config-default/config-lgsm/cs2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/cs2server/_default.cfg @@ -23,6 +23,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-dedicated -ip ${ip} -port ${port} -maxplayers ${maxplayers} -authkey ${wsapikey} +exec ${selfname}.cfg" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -111,6 +115,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/csczserver/_default.cfg b/lgsm/config-default/config-lgsm/csczserver/_default.cfg index 531e897adc..93abb3a4da 100644 --- a/lgsm/config-default/config-lgsm/csczserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/csczserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game czero -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/csgoserver/_default.cfg b/lgsm/config-default/config-lgsm/csgoserver/_default.cfg index a5887c0b05..31fc9c836f 100644 --- a/lgsm/config-default/config-lgsm/csgoserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/csgoserver/_default.cfg @@ -43,6 +43,7 @@ tickrate="64" ## Game Server Login Token (GSLT): Required # GSLT is required for running a public server. +# The GSLT must be created using the App ID set in clientappid (default 4465480). # More info: https://docs.linuxgsm.com/steamcmd/gslt gslt="" @@ -55,6 +56,10 @@ wsstartmap="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game csgo -usercon -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +sv_setsteamaccount ${gslt} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers_override ${maxplayers} +mapgroup ${mapgroup} +game_type ${gametype} +game_mode ${gamemode} +sv_game_mode_flags ${gamemodeflags} +sv_skirmish_id ${skirmishid} +host_workshop_collection ${wscollectionid} +workshop_start_map ${wsstartmap} -authkey ${wsapikey} -nobreakpad" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -143,6 +148,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -151,6 +161,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" @@ -168,8 +183,12 @@ ansi="on" sleeptime="0.5" ## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd -# Server appid +# App ID SteamCMD downloads the dedicated server files from. Do not change. appid="740" +# App ID the server advertises to players. Only clients of this App ID can connect, and the GSLT must be created for it. +# 4465480: standalone CS:GO | 730: CS2 csgo_legacy beta branch | "": leave steam_appid.txt and steam.inf unmanaged +# https://docs.linuxgsm.com/game-servers/counter-strike-global-offensive#client-app-id +clientappid="4465480" steamcmdforcewindows="no" # SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch branch="" diff --git a/lgsm/config-default/config-lgsm/csserver/_default.cfg b/lgsm/config-default/config-lgsm/csserver/_default.cfg index 4e598cd164..a0f89e1735 100644 --- a/lgsm/config-default/config-lgsm/csserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/csserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game cstrike -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/cssserver/_default.cfg b/lgsm/config-default/config-lgsm/cssserver/_default.cfg index ce79d31474..085319420c 100644 --- a/lgsm/config-default/config-lgsm/cssserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/cssserver/_default.cfg @@ -24,6 +24,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game cstrike -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +sv_setsteamaccount ${gslt} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -112,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -120,6 +129,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/cswonserver/_default.cfg b/lgsm/config-default/config-lgsm/cswonserver/_default.cfg new file mode 100644 index 0000000000..7fe44a84c4 --- /dev/null +++ b/lgsm/config-default/config-lgsm/cswonserver/_default.cfg @@ -0,0 +1,206 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters +ip="0.0.0.0" +port="27015" +clientport="27005" +defaultmap="de_dust2" +maxplayers="16" + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +startparameters="-game cstrike -binary ./hlds_i686 -noipx -insecure +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Matrix Alerts | https://docs.linuxgsm.com/alerts/matrix +matrixalert="off" +matrixhomeserver="matrix.org" +matrixtoken="accesstoken" +matrixroom="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="1" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +stopmode="9" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="4" +querytype="protocol-valve-won" + +## Console type +consoleverbose="yes" +consoleinteract="yes" + +## Game Server Details +# Do not edit +gamename="Counter-Strike: WON2" +engine="goldsrc" +glibc="2.0" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}/cstrike" +executabledir="${serverfiles}" +executable="./hlds_run" +servercfgdir="${systemdir}" +servercfg="${selfname}.cfg" +servercfgdefault="server.cfg" +servercfgfullpath="${servercfgdir}/${servercfg}" + +## Backup Directory +backupdir="${lgsmdir}/backup" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +gamelogdir="${systemdir}/logs" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/ctserver/_default.cfg b/lgsm/config-default/config-lgsm/ctserver/_default.cfg index e32f65fa4b..34295f21ab 100644 --- a/lgsm/config-default/config-lgsm/ctserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/ctserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-batchmode -showlogs" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/dabserver/_default.cfg b/lgsm/config-default/config-lgsm/dabserver/_default.cfg index 575c163cfd..e347f3e246 100644 --- a/lgsm/config-default/config-lgsm/dabserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/dabserver/_default.cfg @@ -19,6 +19,10 @@ maxplayers="10" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +124,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/dayzserver/_default.cfg b/lgsm/config-default/config-lgsm/dayzserver/_default.cfg index e55b0f3fd9..2520c59909 100644 --- a/lgsm/config-default/config-lgsm/dayzserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/dayzserver/_default.cfg @@ -27,6 +27,13 @@ mods="" ## Server-side Mods servermods="" +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to serverfiles/workshop and added to -mod= in the order listed. +# Run ./dayzserver workshop-update after changing, or let update apply it. +# workshopmods="1559212036" +workshopmods="" + ## Path to BattlEye # Leave empty for default bepath="" @@ -34,6 +41,10 @@ bepath="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-ip=${ip} -port=${port} -config=${servercfgfullpath} -mod=${mods} -servermod=${servermods} -bepath=${bepath} -limitFPS=60 -dologs -adminlog -freezeCheck" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -122,6 +133,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/dmcserver/_default.cfg b/lgsm/config-default/config-lgsm/dmcserver/_default.cfg index b7f80ade0b..6a0cb7a3e9 100644 --- a/lgsm/config-default/config-lgsm/dmcserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/dmcserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game dmc -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/dodrserver/_default.cfg b/lgsm/config-default/config-lgsm/dodrserver/_default.cfg index 947ee2dab4..a4edba7f1a 100644 --- a/lgsm/config-default/config-lgsm/dodrserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/dodrserver/_default.cfg @@ -17,6 +17,10 @@ queryport="27015" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-MultiHome=${ip} -Port=${port} -QueryPort=${queryport} -SteamServerName='${servername}' -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/dodserver/_default.cfg b/lgsm/config-default/config-lgsm/dodserver/_default.cfg index 6d1f1e28e3..7df687ae86 100644 --- a/lgsm/config-default/config-lgsm/dodserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/dodserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game dod -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/dodsserver/_default.cfg b/lgsm/config-default/config-lgsm/dodsserver/_default.cfg index dc1e162e1f..5205da64d5 100644 --- a/lgsm/config-default/config-lgsm/dodsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/dodsserver/_default.cfg @@ -19,6 +19,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game dod -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +124,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/doiserver/_default.cfg b/lgsm/config-default/config-lgsm/doiserver/_default.cfg index 58b31c2066..dc568296e5 100644 --- a/lgsm/config-default/config-lgsm/doiserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/doiserver/_default.cfg @@ -20,6 +20,10 @@ tickrate="64" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game doi -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers} -workshop -norestart" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -108,6 +112,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -116,6 +125,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/dstserver/_default.cfg b/lgsm/config-default/config-lgsm/dstserver/_default.cfg index 489f748c79..35e954829c 100644 --- a/lgsm/config-default/config-lgsm/dstserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/dstserver/_default.cfg @@ -21,6 +21,10 @@ confdir="DoNotStarveTogether" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-persistent_storage_root ${persistentstorageroot} -conf_dir ${confdir} -cluster ${cluster} -shard ${shard}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -109,6 +113,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/dysserver/_default.cfg b/lgsm/config-default/config-lgsm/dysserver/_default.cfg index 0c7fe66e3f..ee2b9c3715 100644 --- a/lgsm/config-default/config-lgsm/dysserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/dysserver/_default.cfg @@ -24,6 +24,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game "${serverfiles}/dystopia" -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +sv_setsteamaccount ${gslt} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -112,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -120,6 +129,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/ecoserver/_default.cfg b/lgsm/config-default/config-lgsm/ecoserver/_default.cfg index af9bde4591..0514f10195 100644 --- a/lgsm/config-default/config-lgsm/ecoserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/ecoserver/_default.cfg @@ -14,6 +14,10 @@ usertoken="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-nogui -userToken=${usertoken}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -102,6 +106,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/emserver/_default.cfg b/lgsm/config-default/config-lgsm/emserver/_default.cfg index fe02f4434e..e8b6eff462 100644 --- a/lgsm/config-default/config-lgsm/emserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/emserver/_default.cfg @@ -24,6 +24,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game empires -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -112,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -120,6 +129,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/etlserver/_default.cfg b/lgsm/config-default/config-lgsm/etlserver/_default.cfg index 6dd1ccb1ef..3f8a3ebf6e 100644 --- a/lgsm/config-default/config-lgsm/etlserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/etlserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set net_strict 1 +set fs_homepath ${serverfiles} +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/ets2server/_default.cfg b/lgsm/config-default/config-lgsm/ets2server/_default.cfg index 4b8095c87a..a3eeb9f000 100644 --- a/lgsm/config-default/config-lgsm/ets2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/ets2server/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-nosingle" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/fctrserver/_default.cfg b/lgsm/config-default/config-lgsm/fctrserver/_default.cfg index ab885b5ea0..ef803e113d 100644 --- a/lgsm/config-default/config-lgsm/fctrserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/fctrserver/_default.cfg @@ -16,7 +16,11 @@ rconpassword="CHANGE_ME" branch="stable" # values: stable, experimental ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters -startparameters="--bind ${ip} --start-server ${serverfiles}/save1.zip --server-settings ${servercfgfullpath} --port ${port} --rcon-port ${rconport} --rcon-password ${rconpassword}" +startparameters="--bind ${ip} --start-server-load-latest --server-settings ${servercfgfullpath} --port ${port} --rcon-port ${rconport} --rcon-password ${rconpassword}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" #### LinuxGSM Settings #### @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/fivemserver/_default.cfg b/lgsm/config-default/config-lgsm/fivemserver/_default.cfg new file mode 100644 index 0000000000..f48ccbd0a8 --- /dev/null +++ b/lgsm/config-default/config-lgsm/fivemserver/_default.cfg @@ -0,0 +1,205 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +## Game Server Docs | https://docs.fivem.net/docs/server-manual/setting-up-a-server-vanilla/ +# Ports, server name, max players and the license key (sv_licenseKey) are set in server.cfg. +startparameters="+exec ${servercfg}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Matrix Alerts | https://docs.linuxgsm.com/alerts/matrix +matrixalert="off" +matrixhomeserver="matrix.org" +matrixtoken="accesstoken" +matrixroom="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="5" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +# 12: shutdown +# 13: soulmask +# 14: Running With Rifles +# 15: Rising World +# 16: Conan Exiles +stopmode="3" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="3" +querytype="gta5f" + +## Console type +consoleverbose="yes" +consoleinteract="yes" + +## Game Server Details +# Do not edit +gamename="FiveM" +engine="cfx" +glibc="null" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}" +executabledir="${serverfiles}" +executable="./run.sh" +servercfgdir="${systemdir}" +servercfg="server.cfg" +servercfgdefault="server.cfg" +servercfgfullpath="${servercfgdir}/${servercfg}" + +## Backup Directory +backupdir="${lgsmdir}/backup" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/fofserver/_default.cfg b/lgsm/config-default/config-lgsm/fofserver/_default.cfg index 926b95b050..9947ec4117 100644 --- a/lgsm/config-default/config-lgsm/fofserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/fofserver/_default.cfg @@ -19,6 +19,10 @@ maxplayers="20" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game fof -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +124,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/gmodserver/_default.cfg b/lgsm/config-default/config-lgsm/gmodserver/_default.cfg index ca2ad6be72..3760313844 100644 --- a/lgsm/config-default/config-lgsm/gmodserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/gmodserver/_default.cfg @@ -29,6 +29,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game garrysmod -strictportbind -ip ${ip} -port ${port} -tickrate ${tickrate} +host_workshop_collection ${wscollectionid} +clientport ${clientport} +tv_port ${sourcetvport} +gamemode ${gamemode} +map ${defaultmap} +sv_setsteamaccount ${gslt} +servercfgfile ${servercfg} -maxplayers ${maxplayers} -disableluarefresh" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -117,6 +121,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -125,6 +134,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/hcuserver/_default.cfg b/lgsm/config-default/config-lgsm/hcuserver/_default.cfg index c0fdcc630d..7e0fc55867 100644 --- a/lgsm/config-default/config-lgsm/hcuserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/hcuserver/_default.cfg @@ -19,6 +19,10 @@ servername="LinuxGSM" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="${defaultmap}?MaxPlayers=${maxplayers} -ServerName='${servername}' -Port=${port} -QueryPort=${queryport}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + ## Server Parameters for Plague mode #startparameters="${defaultmap}?Game=PL?MapList=KidsBedroom,Garden,Hallway_Simple,Attic_Daytime,Garage,Shed,Kitchen,Hallway_Hard,ToyPalace,Bathroom?MaxPlayers=${maxplayers}?WeaponTypes=7?TimeLimit=600 -ServerName='${servername}' -Port=${port} -QueryPort=${queryport} -NOCONSOLE -unattended" @@ -114,6 +118,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/hl2dmserver/_default.cfg b/lgsm/config-default/config-lgsm/hl2dmserver/_default.cfg index 2e9afaec11..914f83759f 100644 --- a/lgsm/config-default/config-lgsm/hl2dmserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/hl2dmserver/_default.cfg @@ -21,6 +21,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game hl2mp -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -109,6 +113,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -117,6 +126,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/hldmserver/_default.cfg b/lgsm/config-default/config-lgsm/hldmserver/_default.cfg index 697341250d..98bafb2903 100644 --- a/lgsm/config-default/config-lgsm/hldmserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/hldmserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game valve -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/hldmsserver/_default.cfg b/lgsm/config-default/config-lgsm/hldmsserver/_default.cfg index 6f2d90fb42..7153d9c761 100644 --- a/lgsm/config-default/config-lgsm/hldmsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/hldmsserver/_default.cfg @@ -19,6 +19,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game hl1mp -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +124,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/hlwonserver/_default.cfg b/lgsm/config-default/config-lgsm/hlwonserver/_default.cfg new file mode 100644 index 0000000000..0cefba9d37 --- /dev/null +++ b/lgsm/config-default/config-lgsm/hlwonserver/_default.cfg @@ -0,0 +1,206 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters +ip="0.0.0.0" +port="27015" +clientport="27005" +defaultmap="crossfire" +maxplayers="16" + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +startparameters="-game valve -binary ./hlds_i686 -noipx -insecure +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Matrix Alerts | https://docs.linuxgsm.com/alerts/matrix +matrixalert="off" +matrixhomeserver="matrix.org" +matrixtoken="accesstoken" +matrixroom="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="1" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +stopmode="9" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="4" +querytype="protocol-valve-won" + +## Console type +consoleverbose="yes" +consoleinteract="yes" + +## Game Server Details +# Do not edit +gamename="Half-Life: WON2" +engine="goldsrc" +glibc="2.0" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}/valve" +executabledir="${serverfiles}" +executable="./hlds_run" +servercfgdir="${systemdir}" +servercfg="${selfname}.cfg" +servercfgdefault="server.cfg" +servercfgfullpath="${servercfgdir}/${servercfg}" + +## Backup Directory +backupdir="${lgsmdir}/backup" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +gamelogdir="${systemdir}/logs" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/hwserver/_default.cfg b/lgsm/config-default/config-lgsm/hwserver/_default.cfg index c0c4f0eaa8..24762aa772 100644 --- a/lgsm/config-default/config-lgsm/hwserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/hwserver/_default.cfg @@ -27,7 +27,18 @@ loadsave="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters # http://hurtworld.wikia.com/wiki/Hosting_A_Server -startparameters="-batchmode -nographics -logfile ${gamelog} -exec \"host ${port} ${defaultmap} ${loadsave};queryport ${queryport};maxplayers ${maxplayers};servername ${servername};creativemode ${creativemode};addadmin ${admins}\"" +startparameters="-batchmode -nographics -logfile ${gamelog} -exec \"host ${port} ${defaultmap} ${loadsave};queryport ${queryport};maxplayers ${maxplayers};servername ${servername};creativemode ${creativemode}${workshoploadmods};addadmin ${admins}\"" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Downloaded with SteamCMD and loaded with loadmod on start. If you set your own startparameters, keep ${workshoploadmods} in -exec. +# Run ./hwserver workshop-update after changing, or let update apply it. +# workshopmods="2015422570" +workshopmods="" #### LinuxGSM Settings #### @@ -117,6 +128,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/hytserver/_default.cfg b/lgsm/config-default/config-lgsm/hytserver/_default.cfg new file mode 100644 index 0000000000..d98174c77c --- /dev/null +++ b/lgsm/config-default/config-lgsm/hytserver/_default.cfg @@ -0,0 +1,208 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters +# A Hytale account that owns the game is needed for two one-time logins: +# 1. Install: the Hytale downloader shows a login URL to approve in a browser (also in docker logs). +# 2. First start: LinuxGSM shows the server login URL (and sends it as an alert) to approve. +# The server saves it (Server/auth.enc) and restores it on restart. To log in again manually: +# ./hytserver send "/auth login device" +# https://docs.linuxgsm.com/game-servers/hytale +# Server name, password and max players are set in Server/config.json, created on first start. +ip="0.0.0.0" +port="5520" + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +startparameters="--bind ${ip}:${port}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Release Settings +# Patchline (release|pre-release) +hytalepatchline="release" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="1" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +stopmode="5" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="1" +querytype="" + +## Console type +consoleverbose="yes" +consoleinteract="yes" + +## Game Server Details +# Do not edit +gamename="Hytale" +engine="hytale" +glibc="null" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}/Server" +executabledir="${serverfiles}" +executable="./start.sh" +servercfgdir="${systemdir}" +servercfg="config.json" +servercfgdefault="config.json" +servercfgfullpath="${servercfgdir}/${servercfg}" + +## Backup Directory +backupdir="${lgsmdir}/backup" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +gamelogdir="${systemdir}/logs" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/hzserver/_default.cfg b/lgsm/config-default/config-lgsm/hzserver/_default.cfg index 32fb9d6cd2..12f5c5af11 100644 --- a/lgsm/config-default/config-lgsm/hzserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/hzserver/_default.cfg @@ -16,6 +16,10 @@ queryport="27015" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-log -port=${port} -queryport=${queryport} -steamservername=${servername}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -102,6 +106,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/insserver/_default.cfg b/lgsm/config-default/config-lgsm/insserver/_default.cfg index afa7f7f270..e377685b41 100644 --- a/lgsm/config-default/config-lgsm/insserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/insserver/_default.cfg @@ -25,6 +25,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game insurgency -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} -tickrate ${tickrate} +sv_setsteamaccount ${gslt} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers} -workshop -norestart" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -113,6 +117,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -121,6 +130,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/inssserver/_default.cfg b/lgsm/config-default/config-lgsm/inssserver/_default.cfg index 27974e8a0c..ebd573677d 100644 --- a/lgsm/config-default/config-lgsm/inssserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/inssserver/_default.cfg @@ -28,6 +28,10 @@ gslt="" ## Game Server Docs | https://mod.io/g/insurgencysandstorm/r/server-admin-guide startparameters="${defaultmap}?Scenario=${defaultscenario}?MaxPlayers=${maxplayers} -Port=${port} -QueryPort=${queryport} -hostname='${servername}' -Rcon -RconPassword=${rconpassword} -RconListenPort=${rconport} -GSLTToken=${gslt} -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -116,6 +120,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/iosserver/_default.cfg b/lgsm/config-default/config-lgsm/iosserver/_default.cfg index 9286669841..e6be819052 100644 --- a/lgsm/config-default/config-lgsm/iosserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/iosserver/_default.cfg @@ -19,6 +19,10 @@ maxplayers="32" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game iosoccer -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +124,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" @@ -172,7 +186,7 @@ consoleinteract="yes" # Do not edit gamename="IOSoccer" engine="source" -glibc="2.3.6" +glibc="2.29" #### Directories #### # Edit with care @@ -180,7 +194,7 @@ glibc="2.3.6" ## Game Server Directories systemdir="${serverfiles}/iosoccer" executabledir="${serverfiles}" -executable="./srcds_run" +executable="./srcds_run_64" servercfgdir="${systemdir}/cfg" servercfg="${selfname}.cfg" servercfgdefault="server.cfg" diff --git a/lgsm/config-default/config-lgsm/jbep3server/_default.cfg b/lgsm/config-default/config-lgsm/jbep3server/_default.cfg index 2036d3522a..53dc1aab3c 100644 --- a/lgsm/config-default/config-lgsm/jbep3server/_default.cfg +++ b/lgsm/config-default/config-lgsm/jbep3server/_default.cfg @@ -19,6 +19,10 @@ maxplayers="24" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game jbep3 -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -97,6 +101,15 @@ telegramthreadid="" telegramsilentnotification="false" curlcustomstring="" +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -105,6 +118,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/jc2server/_default.cfg b/lgsm/config-default/config-lgsm/jc2server/_default.cfg index afe6d4e83a..eb9f356b7f 100644 --- a/lgsm/config-default/config-lgsm/jc2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/jc2server/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/jc3server/_default.cfg b/lgsm/config-default/config-lgsm/jc3server/_default.cfg index 7d45d966ed..3f4138a266 100644 --- a/lgsm/config-default/config-lgsm/jc3server/_default.cfg +++ b/lgsm/config-default/config-lgsm/jc3server/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/jk2server/_default.cfg b/lgsm/config-default/config-lgsm/jk2server/_default.cfg index 1749c3dd59..22844d9a86 100644 --- a/lgsm/config-default/config-lgsm/jk2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/jk2server/_default.cfg @@ -20,6 +20,10 @@ defaultmap="ffa_bespin" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set net_ip ${ip} +set net_port ${port} +map ${defaultmap} +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -108,6 +112,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/jk3server/_default.cfg b/lgsm/config-default/config-lgsm/jk3server/_default.cfg new file mode 100644 index 0000000000..5bf9ff838c --- /dev/null +++ b/lgsm/config-default/config-lgsm/jk3server/_default.cfg @@ -0,0 +1,219 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +## SteamCMD Login | https://docs.linuxgsm.com/steamcmd#steamcmd-login +# Requires a Steam account that owns Jedi Academy. +steamuser="username" +steampass='password' + +## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters +ip="0.0.0.0" +port="29070" +defaultmap="mp/ffa3" + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +startparameters="+set dedicated 2 +set fs_basepath \"${systemdir}\" +set fs_homepath \"${systemdir}\" +set net_ip ${ip} +set net_port ${port} +exec ${servercfg} +map ${defaultmap}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Matrix Alerts | https://docs.linuxgsm.com/alerts/matrix +matrixalert="off" +matrixhomeserver="matrix.org" +matrixtoken="accesstoken" +matrixroom="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="1" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd +# Server appid +appid="6020" +steamcmdforcewindows="yes" +# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch +branch="" +betapassword="" +# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server +steammaster="false" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +stopmode="3" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="2" +querytype="protocol-quake3" + +## Console type +consoleverbose="yes" +consoleinteract="yes" + +## Game Server Details +# Do not edit +gamename="Jedi Knight: Jedi Academy" +engine="idtech3" +glibc="2.34" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}/GameData" +executabledir="${systemdir}" +executable="./openjkded.x86_64" +servercfg="${selfname}.cfg" +servercfgdefault="server.cfg" +servercfgdir="${systemdir}/base" +servercfgfullpath="${servercfgdir}/${servercfg}" + +## Backup Directory +backupdir="${lgsmdir}/backups" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +gamelogdir="${systemdir}/logs" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/kf2server/_default.cfg b/lgsm/config-default/config-lgsm/kf2server/_default.cfg index 832cc8cfd4..24335c67e7 100644 --- a/lgsm/config-default/config-lgsm/kf2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/kf2server/_default.cfg @@ -17,6 +17,10 @@ gamemode="KFGameContent.KFGameInfo_VersusSurvival" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="\"${defaultmap}?Game=${gamemode}?ConfigSubDir=${selfname} -QueryPort=${queryport}\"" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/kfserver/_default.cfg b/lgsm/config-default/config-lgsm/kfserver/_default.cfg index 323142d690..0dc0e7bc0b 100644 --- a/lgsm/config-default/config-lgsm/kfserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/kfserver/_default.cfg @@ -19,6 +19,10 @@ defaultmap="KF-BioticsLab.rom" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="server ${defaultmap}?game=KFmod.KFGameType?VACSecured=true -nohomedir ini=${servercfg} log=${gamelog}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + ## Server Parameters for Objective mode #defaultmap="KFO-Steamland" #startparameters="server ${defaultmap}?Game=KFStoryGame.KFStoryGame?VACSecured=true -nohomedir ini=${servercfg} log=${gamelog}" @@ -111,6 +115,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/l4d2server/_default.cfg b/lgsm/config-default/config-lgsm/l4d2server/_default.cfg index 3e15847063..8e8cf5767a 100644 --- a/lgsm/config-default/config-lgsm/l4d2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/l4d2server/_default.cfg @@ -18,6 +18,16 @@ maxplayers="8" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game left4dead2 -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to serverfiles/workshop and linked into left4dead2/addons. Run ./l4d2server workshop-update after changing, or let update apply it. +# workshopmods="3815658696" +workshopmods="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +129,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/l4dserver/_default.cfg b/lgsm/config-default/config-lgsm/l4dserver/_default.cfg index 354bb9b194..ed163f8633 100644 --- a/lgsm/config-default/config-lgsm/l4dserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/l4dserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="8" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game left4dead -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" @@ -152,7 +166,7 @@ steammaster="false" # 9: GoldSrc # 10: Avorion # 11: end -stopmode="2" +stopmode="3" ## Query mode # 1: session only diff --git a/lgsm/config-default/config-lgsm/scpslsmserver/_default.cfg b/lgsm/config-default/config-lgsm/luantiserver/_default.cfg similarity index 84% rename from lgsm/config-default/config-lgsm/scpslsmserver/_default.cfg rename to lgsm/config-default/config-lgsm/luantiserver/_default.cfg index eca5c43e6f..fd35a5b7b5 100644 --- a/lgsm/config-default/config-lgsm/scpslsmserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/luantiserver/_default.cfg @@ -9,12 +9,17 @@ #### Game Server Settings #### ## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters -## All server settings except the server port are done in the config file: -## Docs: https://en.scpslgame.com/index.php?title=Docs:Server_Config -port="7777" +ip="0.0.0.0" +port="30000" +gameid="minetest" +worldname="world" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters -startparameters="${port}" +startparameters="--config ${servercfgfullpath} --world ${serverfiles}/worlds/${worldname} --gameid ${gameid} --port ${port} --logfile ${gamelogdir}/${selfname}-game.log --terminal" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" #### LinuxGSM Settings #### @@ -104,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -128,16 +138,6 @@ ansi="on" ## Message Display Time | https://docs.linuxgsm.com/features/message-display-time sleeptime="0.5" -## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd -# Server appid -appid="786920" -steamcmdforcewindows="no" -# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch -branch="" -betapassword="" -# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server -steammaster="false" - ## Stop Mode | https://docs.linuxgsm.com/features/stop-mode # 1: tmux kill # 2: CTRL+c @@ -150,7 +150,7 @@ steammaster="false" # 9: GoldSrc # 10: Avorion # 11: end -stopmode="7" +stopmode="2" ## Query mode # 1: session only @@ -167,20 +167,20 @@ consoleinteract="yes" ## Game Server Details # Do not edit -gamename="SCP: Secret Laboratory ServerMod" -engine="unity3d" -glibc="2.27" +gamename="Luanti" +engine="luanti" +glibc="2.31" #### Directories #### # Edit with care ## Game Server Directories systemdir="${serverfiles}" -executabledir="${systemdir}" -executable="./LocalAdmin" -servercfg="config_gameplay.txt" -servercfgdefault="config_gameplay.txt" -servercfgdir="${HOME}/.config/SCP Secret Laboratory/config/${port}" +executabledir="${serverfiles}/bin" +executable="./luantiserver" +servercfgdir="${systemdir}" +servercfg="${selfname}.cfg" +servercfgdefault="minetest.conf.example" servercfgfullpath="${servercfgdir}/${servercfg}" ## Backup Directory @@ -188,7 +188,7 @@ backupdir="${lgsmdir}/backup" ## Logging Directories [ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" -gamelogdir="${HOME}/.config/SCP Secret Laboratory/LocalAdminLogs/${port}" +gamelogdir="${logdir}/server" lgsmlogdir="${logdir}/script" consolelogdir="${logdir}/console" lgsmlog="${lgsmlogdir}/${selfname}-script.log" diff --git a/lgsm/config-default/config-lgsm/mcbserver/_default.cfg b/lgsm/config-default/config-lgsm/mcbserver/_default.cfg index 5714bd328b..954c42e965 100644 --- a/lgsm/config-default/config-lgsm/mcbserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/mcbserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + # Version (latest|1.18.33.02) mcversion="latest" @@ -102,6 +106,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/mcserver/_default.cfg b/lgsm/config-default/config-lgsm/mcserver/_default.cfg index 1ae68b8e32..ee7d871ef9 100644 --- a/lgsm/config-default/config-lgsm/mcserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/mcserver/_default.cfg @@ -14,6 +14,10 @@ javaram="1024" # -Xmx$1024M ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="nogui" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + ## Release Settings | https://docs.linuxgsm.com/game-servers/minecraft#release-settings # Branch (release|snapshot) branch="release" @@ -108,6 +112,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/mcvserver/_default.cfg b/lgsm/config-default/config-lgsm/mcvserver/_default.cfg index 3d822892a2..135900b2f2 100644 --- a/lgsm/config-default/config-lgsm/mcvserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/mcvserver/_default.cfg @@ -22,6 +22,10 @@ tickrate="64" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game vietnam -usercon -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers_override ${maxplayers} +game_type ${game_type} +game_mode ${game_mode} -nobreakpad" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -88,6 +92,15 @@ telegramtoken="accesstoken" telegramchatid="" curlcustomstring="" +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -96,6 +109,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/mhserver/_default.cfg b/lgsm/config-default/config-lgsm/mhserver/_default.cfg index a8a86b4464..d7ec8d55dd 100644 --- a/lgsm/config-default/config-lgsm/mhserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/mhserver/_default.cfg @@ -20,6 +20,10 @@ defaultmap="FFA_ThePit" ## Game Server Docs | https://mordhau.fandom.com/wiki/Dedicated_Server_Hosting_Guide startparameters="Mordhau ${defaultmap} -MultiHome=${ip} -Port=${port} -BeaconPort=${beaconport} -QueryPort=${queryport} -GameIni=${servercfgfullpath} -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -108,6 +112,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/mohaaserver/_default.cfg b/lgsm/config-default/config-lgsm/mohaaserver/_default.cfg index df8e01fe07..c43978c53b 100644 --- a/lgsm/config-default/config-lgsm/mohaaserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/mohaaserver/_default.cfg @@ -16,6 +16,10 @@ defaultmap="dm/mohdm1" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set fs_outputpath ${gamelogdir} +set dedicated 2 +set net_ip ${ip} +set net_port ${port} +map ${defaultmap} +exec ${servercfg} " +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +108,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -150,7 +159,7 @@ querytype="" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/momserver/_default.cfg b/lgsm/config-default/config-lgsm/momserver/_default.cfg index ec376c3610..9096e7d098 100644 --- a/lgsm/config-default/config-lgsm/momserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/momserver/_default.cfg @@ -17,6 +17,10 @@ beaconport="15000" ## Game Server Docs | https://memoriesofmars.fandom.com/wiki/Dedicated_Servers startparameters="-MultiHome=${ip} -Port=${port} -BeaconPort=${beaconport} -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/mtaserver/_default.cfg b/lgsm/config-default/config-lgsm/mtaserver/_default.cfg index 835b4c4e0a..f6546e092a 100644 --- a/lgsm/config-default/config-lgsm/mtaserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/mtaserver/_default.cfg @@ -14,6 +14,10 @@ ip="0.0.0.0" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -102,6 +106,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/ndserver/_default.cfg b/lgsm/config-default/config-lgsm/ndserver/_default.cfg index f41567bfff..93df86fd6d 100644 --- a/lgsm/config-default/config-lgsm/ndserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/ndserver/_default.cfg @@ -8,6 +8,11 @@ #### Game Server Settings #### +## SteamCMD Login | https://docs.linuxgsm.com/steamcmd#steamcmd-login +# The Steam account must own Nuclear Dawn. The server game content is part of the game. +steamuser="username" +steampass='password' + ## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters ip="0.0.0.0" port="27015" @@ -19,6 +24,10 @@ maxplayers="32" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game nucleardawn -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +129,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/necserver/_default.cfg b/lgsm/config-default/config-lgsm/necserver/_default.cfg index 1b3ae48f34..10132c1876 100644 --- a/lgsm/config-default/config-lgsm/necserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/necserver/_default.cfg @@ -14,6 +14,10 @@ worldname="MyWorld" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-localdir -world ${worldname}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -102,6 +106,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -161,7 +170,7 @@ querytype="" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/nmrihserver/_default.cfg b/lgsm/config-default/config-lgsm/nmrihserver/_default.cfg index 106658818b..5fe65c0d31 100644 --- a/lgsm/config-default/config-lgsm/nmrihserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/nmrihserver/_default.cfg @@ -24,6 +24,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game nmrih -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +sv_setsteamaccount ${gslt} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -112,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -120,6 +129,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/ns2cserver/_default.cfg b/lgsm/config-default/config-lgsm/ns2cserver/_default.cfg index fdd809dff1..6fc341a382 100644 --- a/lgsm/config-default/config-lgsm/ns2cserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/ns2cserver/_default.cfg @@ -26,6 +26,10 @@ serverpassword="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-name '${servername}' -port ${port} -webadmin -webdomain ${ip} -webuser ${httpuser} -webpassword '${httppassword}' -webport ${httpport} -map ${defaultmap} -limit ${maxplayers} -config_path '${servercfgdir}' -modstorage '${modstoragedir}' -mods '${mods}'" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -114,6 +118,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -160,7 +169,7 @@ steammaster="true" # 9: GoldSrc # 10: Avorion # 11: end -stopmode="6" +stopmode="2" ## Query mode # 1: session only diff --git a/lgsm/config-default/config-lgsm/ns2server/_default.cfg b/lgsm/config-default/config-lgsm/ns2server/_default.cfg index d8da66429e..5eeb8d7a80 100644 --- a/lgsm/config-default/config-lgsm/ns2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/ns2server/_default.cfg @@ -27,6 +27,10 @@ serverpassword="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-name '${servername}' -port ${port} -webadmin -webdomain ${ip} -webuser ${httpuser} -webpassword '${httppassword}' -webport ${httpport} -startmodserver -modserverport ${modserverport} -map ${defaultmap} -limit ${maxplayers} -speclimit ${maxspectators} -config_path '${servercfgdir}' -logdir '${gamelogdir}' -modstorage '${modstoragedir}'" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -115,6 +119,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -161,7 +170,7 @@ steammaster="true" # 9: GoldSrc # 10: Avorion # 11: end -stopmode="6" +stopmode="2" ## Query mode # 1: session only diff --git a/lgsm/config-default/config-lgsm/nsserver/_default.cfg b/lgsm/config-default/config-lgsm/nsserver/_default.cfg index 7c981081f9..826d1273c4 100644 --- a/lgsm/config-default/config-lgsm/nsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/nsserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game ns -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/ohdserver/_default.cfg b/lgsm/config-default/config-lgsm/ohdserver/_default.cfg index 17d4c8a186..947f70ec12 100644 --- a/lgsm/config-default/config-lgsm/ohdserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/ohdserver/_default.cfg @@ -21,6 +21,17 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="${defaultmap}?MaxPlayers=${maxplayers} -MultiHome=${ip} -Port=${port} -QueryPort=${queryport} -RconPort=${rconport} -SteamServerName='${servername}' -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to HarshDoorstop/Mods. Select mod maps and modes with defaultmap or startparameters. +# Run ./ohdserver workshop-update after changing, or let update apply it. +# workshopmods="3131976970" +workshopmods="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -109,6 +120,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/onsetserver/_default.cfg b/lgsm/config-default/config-lgsm/onsetserver/_default.cfg index 12cabe90da..bfe543607a 100644 --- a/lgsm/config-default/config-lgsm/onsetserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/onsetserver/_default.cfg @@ -12,6 +12,10 @@ ## Game Server Docs | https://dev.playonset.com/wiki/DedicatedServer startparameters="--config ${servercfgfullpath}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -100,6 +104,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -159,7 +168,7 @@ querytype="" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/opforserver/_default.cfg b/lgsm/config-default/config-lgsm/opforserver/_default.cfg index 5501fc6517..05a0d62a84 100644 --- a/lgsm/config-default/config-lgsm/opforserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/opforserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game gearbox -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/orarserver/_default.cfg b/lgsm/config-default/config-lgsm/orarserver/_default.cfg new file mode 100644 index 0000000000..2e73cd1be1 --- /dev/null +++ b/lgsm/config-default/config-lgsm/orarserver/_default.cfg @@ -0,0 +1,208 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +servername="LinuxGSM" +serverpassword="" +port="1234" +advertiseonline="True" +advertiseonlocalnetwork="True" +enablesingleplayer="True" +recordreplays="False" + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +startparameters="--server Server.Name=\"${servername}\" Server.Password=\"${serverpassword}\" Server.ListenPort=${port} Server.AdvertiseOnline=${advertiseonline} Server.AdvertiseOnLocalNetwork=${advertiseonlocalnetwork} Server.EnableSingleplayer=${enablesingleplayer} Server.RecordReplays=${recordreplays} Engine.SupportDir=\"${servercfgdir}\"" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Matrix Alerts | https://docs.linuxgsm.com/alerts/matrix +matrixalert="off" +matrixhomeserver="matrix.org" +matrixtoken="accesstoken" +matrixroom="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="1" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +stopmode="2" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="5" +querytype="" + +## Console type +consoleverbose="yes" +consoleinteract="no" + +## Game Server Details +# Do not edit +gamename="OpenRA: Red Alert" +engine="openra" +glibc="2.17" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}" +executabledir="${serverfiles}/openra" +preexecutable="" +executable="./AppRun" +servercfgdir="${serverfiles}/data/${selfname}" +servercfg="" +servercfgdefault="" +servercfgfullpath="" + +## Backup Directory +backupdir="${lgsmdir}/backup" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +gamelogdir="${servercfgdir}/Logs" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/pc2server/_default.cfg b/lgsm/config-default/config-lgsm/pc2server/_default.cfg index 3ac6eeb77b..d13e8e87af 100644 --- a/lgsm/config-default/config-lgsm/pc2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/pc2server/_default.cfg @@ -15,6 +15,10 @@ steampass='password' ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="--config ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -103,6 +107,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/pcserver/_default.cfg b/lgsm/config-default/config-lgsm/pcserver/_default.cfg index 601ffed3bc..2eb2d9d9b2 100644 --- a/lgsm/config-default/config-lgsm/pcserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/pcserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="--config ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/pmcserver/_default.cfg b/lgsm/config-default/config-lgsm/pmcserver/_default.cfg index db456dbf7b..c70c7d65a0 100644 --- a/lgsm/config-default/config-lgsm/pmcserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/pmcserver/_default.cfg @@ -14,6 +14,10 @@ javaram="1024" # -Xmx$1024M ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="nogui" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + ## Release Settings | https://docs.linuxgsm.com/game-servers/minecraft#release-settings # Version (latest|1.16.5) mcversion="latest" @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/pvkiiserver/_default.cfg b/lgsm/config-default/config-lgsm/pvkiiserver/_default.cfg index 7f27e32a0a..a16e02fee0 100644 --- a/lgsm/config-default/config-lgsm/pvkiiserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/pvkiiserver/_default.cfg @@ -19,6 +19,10 @@ maxplayers="24" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game pvkii -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +124,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/pvrserver/_default.cfg b/lgsm/config-default/config-lgsm/pvrserver/_default.cfg index 85deb664f5..c1719a9116 100644 --- a/lgsm/config-default/config-lgsm/pvrserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/pvrserver/_default.cfg @@ -20,6 +20,10 @@ apikey="" ## Game Server Docs | http://pavlovwiki.com/index.php/Setting_up_a_dedicated_server startparameters="Pavlov ${defaultmap} -MultiHome=${ip} -Port=${port} ApiKey=${apikey} -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +108,15 @@ telegramthreadid="" telegramsilentnotification="false" curlcustomstring="" +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/pwserver/_default.cfg b/lgsm/config-default/config-lgsm/pwserver/_default.cfg index c58ce087f2..f312c9c0f0 100644 --- a/lgsm/config-default/config-lgsm/pwserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/pwserver/_default.cfg @@ -19,6 +19,10 @@ steamport="27015" ## Game Server Docs | https://tech.palworldgame.com/settings-and-operation/arguments startparameters="-publiclobby -useperfthreads -NoAsyncLoadingThread -UseMultithreadForDS -servername='${servername}' -port='${port}' -queryport='${steamport}'" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/pzserver/_default.cfg b/lgsm/config-default/config-lgsm/pzserver/_default.cfg index a0456d6e3a..19313b9009 100644 --- a/lgsm/config-default/config-lgsm/pzserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/pzserver/_default.cfg @@ -13,7 +13,11 @@ ip="0.0.0.0" adminpassword="CHANGE_ME" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters -startparameters="-servername ${selfname}" +startparameters="-servername ${selfname} -adminpassword ${adminpassword}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" #### LinuxGSM Settings #### @@ -103,6 +107,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/q2server/_default.cfg b/lgsm/config-default/config-lgsm/q2server/_default.cfg index 2fe85ea3cb..8a1b1896d9 100644 --- a/lgsm/config-default/config-lgsm/q2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/q2server/_default.cfg @@ -16,6 +16,10 @@ defaultmap="q2dm1" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set dedicated 1 +set ip ${ip} +set port ${port} +exec ${servercfg} +set deathmatch 1 +map ${defaultmap}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +108,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/q3server/_default.cfg b/lgsm/config-default/config-lgsm/q3server/_default.cfg index 24a3604fcc..175ac5aca8 100644 --- a/lgsm/config-default/config-lgsm/q3server/_default.cfg +++ b/lgsm/config-default/config-lgsm/q3server/_default.cfg @@ -16,6 +16,10 @@ defaultmap="q3dm17" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set dedicated 2 +set com_hunkMegs 32 +set net_ip ${ip} +set net_port ${port} +map ${defaultmap} +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +108,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/q4server/_default.cfg b/lgsm/config-default/config-lgsm/q4server/_default.cfg index f4f8f4655c..c274ae12c1 100644 --- a/lgsm/config-default/config-lgsm/q4server/_default.cfg +++ b/lgsm/config-default/config-lgsm/q4server/_default.cfg @@ -18,6 +18,10 @@ port="28004" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set net_port ${port} +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/qlserver/_default.cfg b/lgsm/config-default/config-lgsm/qlserver/_default.cfg index 057b0f09d7..cc5b1d502e 100644 --- a/lgsm/config-default/config-lgsm/qlserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/qlserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/qwserver/_default.cfg b/lgsm/config-default/config-lgsm/qwserver/_default.cfg index b637f7d074..8a95c21000 100644 --- a/lgsm/config-default/config-lgsm/qwserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/qwserver/_default.cfg @@ -15,6 +15,10 @@ port="27500" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-port ${port} -game ktx +exec ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -103,6 +107,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -155,7 +164,7 @@ consoleinteract="yes" # Do not edit gamename="QuakeWorld" engine="quake" -glibc="2.17" +glibc="2.34" #### Directories #### # Edit with care diff --git a/lgsm/config-default/config-lgsm/ricochetserver/_default.cfg b/lgsm/config-default/config-lgsm/ricochetserver/_default.cfg index a1d05ac95a..fedb17b9ae 100644 --- a/lgsm/config-default/config-lgsm/ricochetserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/ricochetserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game ricochet -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/roserver/_default.cfg b/lgsm/config-default/config-lgsm/roserver/_default.cfg index 9d28637358..92daaa4d3f 100644 --- a/lgsm/config-default/config-lgsm/roserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/roserver/_default.cfg @@ -19,6 +19,10 @@ defaultmap="RO-Arad.rom" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="server ${defaultmap}?game=ROGame.ROTeamGame?VACSecured=true -nohomedir ini=${servercfg} log=${gamelog}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/rsdwserver/_default.cfg b/lgsm/config-default/config-lgsm/rsdwserver/_default.cfg new file mode 100644 index 0000000000..a335bccfef --- /dev/null +++ b/lgsm/config-default/config-lgsm/rsdwserver/_default.cfg @@ -0,0 +1,212 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters +# Server name, passwords, owner ID and world name are read by the server from DedicatedServer.ini, not set here. +# Edit them in: serverfiles/RSDragonwilds/Saved/Config/LinuxServer/DedicatedServer.ini +# REQUIRED: the server will not finish starting until OwnerId is set in DedicatedServer.ini +# (your Player ID, shown in the in-game settings). DedicatedServer.ini is created during install, +# so OwnerId can be set before the first start. +port="7777" + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +## Game Server Docs | https://dragonwilds.runescape.wiki/w/Dedicated_Servers +startparameters="-Port=${port} -log" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="5" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd +# Server appid +appid="4019830" +steamcmdforcewindows="no" +# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch +branch="" +betapassword="" +# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server +steammaster="false" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +stopmode="2" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="1" +querytype="" + +## Console type +consoleverbose="yes" +consoleinteract="no" + +## Game Server Details +# Do not edit +gamename="RuneScape: Dragonwilds" +engine="unreal5" +glibc="2.17" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}/RSDragonwilds" +executabledir="${systemdir}/Binaries/Linux" +executable="./RSDragonwildsServer-Linux-Shipping" +servercfgdir="${systemdir}/Saved/Config/LinuxServer" +servercfg="DedicatedServer.ini" +servercfgdefault="DedicatedServer.ini" +servercfgfullpath="${servercfgdir}/${servercfg}" + +## Backup Directory +backupdir="${lgsmdir}/backup" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +gamelogdir="${systemdir}/Saved/Logs" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/rtcwserver/_default.cfg b/lgsm/config-default/config-lgsm/rtcwserver/_default.cfg index f2ba06a62a..be719a5355 100644 --- a/lgsm/config-default/config-lgsm/rtcwserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/rtcwserver/_default.cfg @@ -16,6 +16,10 @@ defaultmap="mp_beach" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set fs_basepath ${serverfiles} +set dedicated 1 +set net_ip ${ip} +set net_port ${port} +exec ${servercfg} +map ${defaultmap}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +108,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -150,7 +159,7 @@ querytype="protocol-quake3" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/rustserver/_default.cfg b/lgsm/config-default/config-lgsm/rustserver/_default.cfg index 418aad9468..105f7d36d4 100644 --- a/lgsm/config-default/config-lgsm/rustserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/rustserver/_default.cfg @@ -31,6 +31,10 @@ tags="" # values: monthly, biweekly, weekly, vanilla, hardcore, softc ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-batchmode +app.listenip ${ip} +app.port ${appport} +server.ip ${ip} +server.port ${port} +server.queryport ${queryport} +server.tickrate ${tickrate} +server.hostname \"${servername}\" +server.identity \"${selfname}\" +server.gamemode ${gamemode} +server.level \"${serverlevel}\" +server.seed ${seed} +server.salt ${salt} +server.maxplayers ${maxplayers} +server.worldsize ${worldsize} +server.saveinterval ${saveinterval} +rcon.web ${rconweb} +rcon.ip ${ip} +rcon.port ${rconport} +rcon.password \"${rconpassword}\" +server.tags ${tags} -logfile ${gamelog}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -119,6 +123,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -165,7 +174,7 @@ steammaster="false" # 9: GoldSrc # 10: Avorion # 11: end -stopmode="2" +stopmode="4" ## Query mode # 1: session only @@ -178,7 +187,7 @@ querytype="protocol-valve" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/rwrserver/_default.cfg b/lgsm/config-default/config-lgsm/rwrserver/_default.cfg new file mode 100644 index 0000000000..b2d4ee4b40 --- /dev/null +++ b/lgsm/config-default/config-lgsm/rwrserver/_default.cfg @@ -0,0 +1,220 @@ +################################## +######## Default Settings ######## +################################## +# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! +# Copy settings from here and use them in either: +# common.cfg - applies settings to every instance. +# [instance].cfg - applies settings to a specific instance. + +#### Game Server Settings #### + +## SteamCMD Login | https://docs.linuxgsm.com/steamcmd#steamcmd-login +# The Steam account must own Running With Rifles. The server is part of the game. +# WW2 game modes also need the account to own the Pacific and/or Edelweiss DLC. +steamuser="username" +steampass='password' + +## Game Mode Script | https://docs.linuxgsm.com/game-servers/running-with-rifles +# Server name, port, comment, mode and max players are set in the start script. +# Edit them in: serverfiles/media/packages/vanilla/scripts/rwrserver.as (a copy of start_invasion.as, created on install). +# For another game mode, set the package and its start script, e.g. +# startpackage="media/packages/deathmatch" and startscript="start_deathmatch_server.as" +startpackage="media/packages/vanilla" +startscript="${selfname}.as" + +## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +## Game Server Docs | https://runningwithrifles.fandom.com/wiki/How_to_host_a_different_game_mode_as_dedicated_server +startparameters="" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +#### LinuxGSM Settings #### + +## LinuxGSM Stats +# Send useful stats to LinuxGSM developers. +# https://docs.linuxgsm.com/configuration/linuxgsm-stats +# (on|off) +stats="off" + +## Notification Alerts +# (on|off) + +# Display IP | https://docs.linuxgsm.com/alerts#display-ip +displayip="" + +# More info | https://docs.linuxgsm.com/alerts#more-info +postalert="off" + +# Alert on Start/Stop/Restart +statusalert="off" + +# Discord Alerts | https://docs.linuxgsm.com/alerts/discord +discordalert="off" +discordwebhook="webhook" + +# Email Alerts | https://docs.linuxgsm.com/alerts/email +emailalert="off" +email="email@example.com" +emailfrom="" + +# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify +gotifyalert="off" +gotifytoken="token" +gotifywebhook="webhook" + +# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt +iftttalert="off" +ifttttoken="accesstoken" +iftttevent="linuxgsm_alert" + +# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy +ntfyalert="off" +ntfytopic="LinuxGSM" +ntfyserver="https://ntfy.sh" +ntfytoken="" +ntfyusername="" +ntfypassword="" +ntfypriority="" +ntfytags="" + +# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet +pushbulletalert="off" +pushbullettoken="accesstoken" +channeltag="" + +# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover +pushoveralert="off" +pushovertoken="accesstoken" +pushoveruserkey="userkey" + +# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat +rocketchatalert="off" +rocketchatwebhook="webhook" + +# Slack Alerts | https://docs.linuxgsm.com/alerts/slack +slackalert="off" +slackwebhook="webhook" + +# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram +# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". +# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". +telegramapi="api.telegram.org" +telegramalert="off" +telegramtoken="accesstoken" +telegramchatid="" +telegramthreadid="" +telegramsilentnotification="false" +curlcustomstring="" + +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + +## Updating | https://docs.linuxgsm.com/commands/update +updateonstart="off" + +## Backup | https://docs.linuxgsm.com/commands/backup +maxbackups="4" +maxbackupdays="30" +stoponbackup="on" + +## Logging | https://docs.linuxgsm.com/features/logging +consolelogging="on" +logdays="7" + +## Monitor | https://docs.linuxgsm.com/commands/monitor +# Query delay time +querydelay="5" + +## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors +ansi="on" + +#### Advanced Settings #### + +## Message Display Time | https://docs.linuxgsm.com/features/message-display-time +sleeptime="0.5" + +## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd +# Server appid +appid="270150" +steamcmdforcewindows="no" +# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch +branch="" +betapassword="" +# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server +steammaster="false" + +## Stop Mode | https://docs.linuxgsm.com/features/stop-mode +# 1: tmux kill +# 2: CTRL+c +# 3: quit +# 4: quit 120s +# 5: stop +# 6: q +# 7: exit +# 8: 7 Days to Die +# 9: GoldSrc +# 10: Avorion +# 11: end +# 12: shutdown +# 13: soulmask +# 14: Running With Rifles +stopmode="14" + +## Query mode +# 1: session only +# 2: gamedig (gsquery fallback) +# 3: gamedig +# 4: gsquery +# 5: tcp +querymode="1" +querytype="" + +## Console type +consoleverbose="yes" +consoleinteract="yes" + +## Game Server Details +# Do not edit +gamename="Running With Rifles" +engine="rwr" +glibc="2.11" + +#### Directories #### +# Edit with care + +## Game Server Directories +systemdir="${serverfiles}" +executabledir="${serverfiles}" +executable="./launch_server" +servercfgdir="${systemdir}/media/packages/vanilla/scripts" +servercfg="${selfname}.as" +servercfgdefault="start_invasion.as" +servercfgfullpath="${servercfgdir}/${servercfg}" + +## Backup Directory +backupdir="${lgsmdir}/backup" + +## Logging Directories +[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" +lgsmlogdir="${logdir}/script" +consolelogdir="${logdir}/console" +lgsmlog="${lgsmlogdir}/${selfname}-script.log" +consolelog="${consolelogdir}/${selfname}-console.log" +alertlog="${lgsmlogdir}/${selfname}-alert.log" +postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" + +## Logs Naming +lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" +consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" + +## Log Parameters +logtimestamp="off" +logtimestampformat="%Y-%m-%d %H:%M:%S" diff --git a/lgsm/config-default/config-lgsm/rwserver/_default.cfg b/lgsm/config-default/config-lgsm/rwserver/_default.cfg index fe8c9f842e..242e468169 100644 --- a/lgsm/config-default/config-lgsm/rwserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/rwserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -145,7 +154,9 @@ steammaster="false" # 9: GoldSrc # 10: Avorion # 11: end -stopmode="3" +# 12: shutdown +# 15: Rising World +stopmode="15" ## Query mode # 1: session only diff --git a/lgsm/config-default/config-lgsm/sampserver/_default.cfg b/lgsm/config-default/config-lgsm/sampserver/_default.cfg index af548a639a..6b54804860 100644 --- a/lgsm/config-default/config-lgsm/sampserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/sampserver/_default.cfg @@ -15,6 +15,10 @@ port="7777" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -103,6 +107,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/sbotsserver/_default.cfg b/lgsm/config-default/config-lgsm/sbotsserver/_default.cfg index 93644efe5b..5fc7e61ce3 100644 --- a/lgsm/config-default/config-lgsm/sbotsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/sbotsserver/_default.cfg @@ -17,6 +17,10 @@ servername="LinuxGSM" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-MultiHome=${ip} -Port=${port} -QueryPort=${queryport} -startup_map ${defaultmap} -server_name '${servername}'" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -105,6 +109,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/sbserver/_default.cfg b/lgsm/config-default/config-lgsm/sbserver/_default.cfg index fbca63afc0..bad8fe6874 100644 --- a/lgsm/config-default/config-lgsm/sbserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/sbserver/_default.cfg @@ -18,6 +18,16 @@ ip="0.0.0.0" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to serverfiles/workshop and linked into serverfiles/mods. Run ./sbserver workshop-update after changing, or let update apply it. +# workshopmods="3816094872" +workshopmods="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/scpslserver/_default.cfg b/lgsm/config-default/config-lgsm/scpslserver/_default.cfg index 2ad4b566ca..2c5dfbf717 100644 --- a/lgsm/config-default/config-lgsm/scpslserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/scpslserver/_default.cfg @@ -14,7 +14,11 @@ port="7777" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters -startparameters="${port}" +startparameters="${port} --acceptEULA" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" #### LinuxGSM Settings #### @@ -104,6 +108,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/sdtdserver/_default.cfg b/lgsm/config-default/config-lgsm/sdtdserver/_default.cfg index 383b51d231..16f45922a8 100644 --- a/lgsm/config-default/config-lgsm/sdtdserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/sdtdserver/_default.cfg @@ -14,6 +14,10 @@ ip="0.0.0.0" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-quit -batchmode -nographics -dedicated -configfile=${servercfgfullpath}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -102,6 +106,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/sfcserver/_default.cfg b/lgsm/config-default/config-lgsm/sfcserver/_default.cfg index 856b172dfe..950fddb375 100644 --- a/lgsm/config-default/config-lgsm/sfcserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/sfcserver/_default.cfg @@ -19,6 +19,10 @@ maxplayers="32" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game sfclassic -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +124,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/sfserver/_default.cfg b/lgsm/config-default/config-lgsm/sfserver/_default.cfg index 1fbcbf52ef..5ed2e6f286 100644 --- a/lgsm/config-default/config-lgsm/sfserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/sfserver/_default.cfg @@ -10,14 +10,17 @@ ## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters ip="0.0.0.0" -queryport="15777" -beaconport="15000" -reliableport="8888" +# Satisfactory 1.0+: port is used for the game (UDP) and the server API (TCP). port="7777" +reliableport="8888" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters ## Game Server Docs | https://satisfactory.fandom.com/wiki/Dedicated_servers -startparameters="FactoryGame -Port=${port} -ServerQueryPort=${queryport} -BeaconPort=${beaconport} -ReliablePort=${reliableport} -log" +startparameters="FactoryGame -Port=${port} -ReliablePort=${reliableport} -log" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" #### LinuxGSM Settings #### @@ -107,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/smserver/_default.cfg b/lgsm/config-default/config-lgsm/smserver/_default.cfg index 029b33306f..311c5f07d6 100644 --- a/lgsm/config-default/config-lgsm/smserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/smserver/_default.cfg @@ -22,6 +22,10 @@ defaultmap="Level01_Main" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="WS ${defaultmap} -MultiHome=${ip} -Port=${port} -EchoPort=${telnetport} -QueryPort=${queryport} -SteamServerName='${servername}' -PSW='${serverpassword}' -adminpsw='${adminpassword}' -MaxPlayers=${maxplayers} -initbackup -backupinterval=${backupinterval} -UTF8Output -forcepassthrough -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,15 @@ telegramthreadid="" telegramsilentnotification="false" curlcustomstring="" +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/sof2server/_default.cfg b/lgsm/config-default/config-lgsm/sof2server/_default.cfg index 88fdfd2391..9f3742f6b8 100644 --- a/lgsm/config-default/config-lgsm/sof2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/sof2server/_default.cfg @@ -16,6 +16,10 @@ defaultmap="mp_shop" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+set sv_punkbuster 0 +set dedicated 2 +set net_ip ${ip} +set net_port ${port} +exec ${servercfg} +map ${defaultmap}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +108,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/solserver/_default.cfg b/lgsm/config-default/config-lgsm/solserver/_default.cfg index 41d83dc5e9..b04ffaca0c 100644 --- a/lgsm/config-default/config-lgsm/solserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/solserver/_default.cfg @@ -15,6 +15,17 @@ maplist="mapslist.txt" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-b ${ip} -m ${maplist} -c ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to serverfiles/workshop and linked into maps, textures and scenery-gfx. Add the maps you want to mapslist.txt. +# Run ./solserver workshop-update after changing, or let update apply it. +# workshopmods="2049686708" +workshopmods="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -103,6 +114,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/squad44server/_default.cfg b/lgsm/config-default/config-lgsm/squad44server/_default.cfg index 0235f155e9..43c5c327fb 100644 --- a/lgsm/config-default/config-lgsm/squad44server/_default.cfg +++ b/lgsm/config-default/config-lgsm/squad44server/_default.cfg @@ -16,6 +16,16 @@ queryport="10037" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-MultiHome=${ip} -Port=${port} -QueryPort=${queryport} -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to PostScriptum/Plugins/Mods. Run ./squad44server workshop-update after changing, or let update apply it. +# workshopmods="2303078092" +workshopmods="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +114,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/squadserver/_default.cfg b/lgsm/config-default/config-lgsm/squadserver/_default.cfg index b19d59ce6b..7615e606ba 100644 --- a/lgsm/config-default/config-lgsm/squadserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/squadserver/_default.cfg @@ -16,6 +16,16 @@ queryport="27165" ## Game Server Docs | https://squad.fandom.com/wiki/Dedicated_server startparameters="-MultiHome=${ip} -Port=${port} -QueryPort=${queryport}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to SquadGame/Plugins/Mods. Run ./squadserver workshop-update after changing, or let update apply it. +# workshopmods="3813515660" +workshopmods="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +114,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/stnserver/_default.cfg b/lgsm/config-default/config-lgsm/stnserver/_default.cfg index d245e780d6..eab5fa6d55 100644 --- a/lgsm/config-default/config-lgsm/stnserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/stnserver/_default.cfg @@ -15,6 +15,10 @@ region="0" # https://colonysurvival.gamepedia.com/Dedicated_Server#Installation_.28Linux.29 startparameters="-mc ${maxplayers} -r ${region}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -103,6 +107,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/stserver/_default.cfg b/lgsm/config-default/config-lgsm/stserver/_default.cfg index c724f2c194..90a49c76fe 100644 --- a/lgsm/config-default/config-lgsm/stserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/stserver/_default.cfg @@ -15,6 +15,16 @@ worldtype="Moon" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-LOAD ${worldsave} ${worldtype}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + +## Steam Workshop Mods | https://docs.linuxgsm.com/steamcmd/workshop +# Workshop item or collection IDs, separated by spaces. Collections are expanded. +# Installed to mods, where the server enables them. Run ./stserver workshop-update after changing, or let update apply it. +# workshopmods="3813753764" +workshopmods="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -103,6 +113,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -149,7 +164,7 @@ steammaster="false" # 9: GoldSrc # 10: Avorion # 11: end -stopmode="3" +stopmode="2" ## Query mode # 1: session only @@ -162,7 +177,7 @@ querytype="" ## Console type consoleverbose="yes" -consoleinteract="yes" +consoleinteract="no" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/svenserver/_default.cfg b/lgsm/config-default/config-lgsm/svenserver/_default.cfg index 60a1e8c7aa..01f299309d 100644 --- a/lgsm/config-default/config-lgsm/svenserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/svenserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game svencoop -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} +maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/terrariaserver/_default.cfg b/lgsm/config-default/config-lgsm/terrariaserver/_default.cfg index 3694c63ba8..f5aa4607df 100644 --- a/lgsm/config-default/config-lgsm/terrariaserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/terrariaserver/_default.cfg @@ -18,6 +18,10 @@ ip="0.0.0.0" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-config ${servercfgfullpath}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/tf2cserver/_default.cfg b/lgsm/config-default/config-lgsm/tf2cserver/_default.cfg index e17cb3cd72..1ce0d66e29 100644 --- a/lgsm/config-default/config-lgsm/tf2cserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/tf2cserver/_default.cfg @@ -26,6 +26,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game tf2classified -tf_path ${supportdir} -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +sv_setsteamaccount ${gslt} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -110,6 +114,15 @@ telegramthreadid="" telegramsilentnotification="false" curlcustomstring="" +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -118,6 +131,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/tf2server/_default.cfg b/lgsm/config-default/config-lgsm/tf2server/_default.cfg index 3bd74259a8..355994fba0 100644 --- a/lgsm/config-default/config-lgsm/tf2server/_default.cfg +++ b/lgsm/config-default/config-lgsm/tf2server/_default.cfg @@ -24,7 +24,11 @@ maxplayers="16" gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters -startparameters="-game tf -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +sv_setsteamaccount ${gslt} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +startparameters="-game tf -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +sv_setsteamaccount ${gslt} +servercfgfile ${servercfg} -maxplayers ${maxplayers} -norestart" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" #### LinuxGSM Settings #### @@ -114,6 +118,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -122,6 +131,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" @@ -179,7 +193,7 @@ consoleinteract="yes" # Do not edit gamename="Team Fortress 2" engine="source" -glibc="2.15" +glibc="2.29" #### Directories #### # Edit with care @@ -187,7 +201,7 @@ glibc="2.15" ## Game Server Directories systemdir="${serverfiles}/tf" executabledir="${serverfiles}" -executable="./srcds_run" +executable="./srcds_run_64" servercfgdir="${systemdir}/cfg" servercfg="${selfname}.cfg" servercfgdefault="server.cfg" diff --git a/lgsm/config-default/config-lgsm/tfcserver/_default.cfg b/lgsm/config-default/config-lgsm/tfcserver/_default.cfg index 123fe1b0b5..7d644d116b 100644 --- a/lgsm/config-default/config-lgsm/tfcserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/tfcserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game tfc -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/tfserver/_default.cfg b/lgsm/config-default/config-lgsm/tfserver/_default.cfg index 43026b5d19..49584cac87 100644 --- a/lgsm/config-default/config-lgsm/tfserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/tfserver/_default.cfg @@ -35,6 +35,10 @@ steamsocket="0" # Use Steam Socket. 0 = off; 1 = on. Use Steam Servers for netwo ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="ProjectWar_Start?DedicatedServer?MaxPlayers=${maxplayers} -server -game -log -MultiHome=${ip} -Port=${port} -QueryPort=${queryport} -BeaconPort=${beaconport} -ShutDownServicePort=${shutdownport} -ConfigServerName='${selfname}' -OutIPAddress=${publicip} -ServerTags='${servertags}' -UseSteamSocket=${steamsocket} -UserDir='${serverfiles}/${selfname}' -ServerName='${servername}' -EnableParallelCharacterMovementTickFunction -EnableParallelCharacterTickFunction -UseDynamicPhysicsScene -Game.PhysicsVehicle=false -ansimalloc -Game.MaxFrameRate=35 -MaxQueueSize=${maxqueuesize} -QueueValidTime=${queuevalidtime} -QueueThreshold=${maxplayers} -ServerFightModeType=${gamemode} -IsCanSelfDamage=${damageself} -IsCanFriendDamage=${damageallies} -SaveWorldInterval=${saveinterval} -GMOverlapRatio=2 -GreenHand=${greenhand} -SensitiveWords=${allowsensitivewords} -UseEAC=${anticheat} -ServerAdminAccounts='${serveradmins}' -IsShowGmTitle=${adminlabel} -ServerPassword='${serverpassword}'" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -123,6 +127,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/tiserver/_default.cfg b/lgsm/config-default/config-lgsm/tiserver/_default.cfg index 59384527b0..34dc148964 100644 --- a/lgsm/config-default/config-lgsm/tiserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/tiserver/_default.cfg @@ -13,9 +13,17 @@ ip="0.0.0.0" port="7777" defaultmap="/Game/TheIsle/Maps/Game/Gateway/Gateway" +## Epic Online Services (EOS) Dedicated Server Credentials +eosclientid="xyza7891gk5PRo3J7G9puCJGFJjmEguW" +eosclientsecret="pKWl6t5i9NJK8gTpVlAxzENZ65P8hYzodV8Dqe5Rlc8" + ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters ## Game Server Docs | https://isle.fandom.com/wiki/The_Isle_Server_Settings_and_Configuration -startparameters="${defaultmap} -Port=${port} -log" +startparameters="${defaultmap} -Port=${port} -log -ini:Engine:[EpicOnlineServices]:DedicatedServerClientId=${eosclientid} -ini:Engine:[EpicOnlineServices]:DedicatedServerClientSecret=${eosclientsecret}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" #### LinuxGSM Settings #### @@ -105,6 +113,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/ts3server/_default.cfg b/lgsm/config-default/config-lgsm/ts3server/_default.cfg index 8b6f0bc339..0e77d9077f 100644 --- a/lgsm/config-default/config-lgsm/ts3server/_default.cfg +++ b/lgsm/config-default/config-lgsm/ts3server/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="inifile=${servercfgfullpath} pid_file=ts3server.pid" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/tsserver/_default.cfg b/lgsm/config-default/config-lgsm/tsserver/_default.cfg index 8ade847bd8..6ba1035261 100644 --- a/lgsm/config-default/config-lgsm/tsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/tsserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="32" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game ts -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers} " +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/tuserver/_default.cfg b/lgsm/config-default/config-lgsm/tuserver/_default.cfg index 3597cac15d..18682d40b3 100644 --- a/lgsm/config-default/config-lgsm/tuserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/tuserver/_default.cfg @@ -21,6 +21,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-MultiHome=${ip} -Port=${port} -QueryPort=${queryport} -TowerServerINI=${selfname}.ini -log" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -109,6 +113,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/twserver/_default.cfg b/lgsm/config-default/config-lgsm/twserver/_default.cfg index d423126ab8..96057e6148 100644 --- a/lgsm/config-default/config-lgsm/twserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/twserver/_default.cfg @@ -18,6 +18,10 @@ ip="0.0.0.0" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-f ${servercfg}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/untserver/_default.cfg b/lgsm/config-default/config-lgsm/untserver/_default.cfg index 5ae3612fe1..577c2f12f3 100644 --- a/lgsm/config-default/config-lgsm/untserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/untserver/_default.cfg @@ -25,6 +25,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-nographics -batchmode -bind ${ip} -port ${port} -maxplayers ${maxplayers} -perspective ${perspective} -mode ${gamemode} -name ${servername} -map ${defaultmap} -gslt ${gslt} +InternetServer/${selfname}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -113,6 +117,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/ut2k4server/_default.cfg b/lgsm/config-default/config-lgsm/ut2k4server/_default.cfg index 40803ef4d9..85e186a243 100644 --- a/lgsm/config-default/config-lgsm/ut2k4server/_default.cfg +++ b/lgsm/config-default/config-lgsm/ut2k4server/_default.cfg @@ -15,6 +15,10 @@ ip="0.0.0.0" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="server ${defaultmap}?game=XGame.xDeathMatch -nohomedir ini=${servercfg} log=${gamelog}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -103,6 +107,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/ut3server/_default.cfg b/lgsm/config-default/config-lgsm/ut3server/_default.cfg index 031a2b0472..df1d297f04 100644 --- a/lgsm/config-default/config-lgsm/ut3server/_default.cfg +++ b/lgsm/config-default/config-lgsm/ut3server/_default.cfg @@ -31,6 +31,10 @@ gspassword="" # List of game types and mutators: https://docs.linuxgsm.com/game-servers/unreal-tournament-3 startparameters="server ${defaultmap}?Game=${game}?bIsDedicated=${isdedicated}?bIsLanMatch=${islanmatch}?bUsesStats=${usesstats}?bShouldAdvertise=${shouldadvertise}?PureServer=${pureserver}?bAllowJoinInProgress=${allowjoininprogress}?Mutator=${mutators}?ConfigSubDir=${selfname} -login=${gsusername} -password=${gspassword} -multihome=${ip} -port=${port} -queryport=${queryport} -nohomedir -unattended -log=${gamelog}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -119,6 +123,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/ut99server/_default.cfg b/lgsm/config-default/config-lgsm/ut99server/_default.cfg index c1506ad38b..69f25f857f 100644 --- a/lgsm/config-default/config-lgsm/ut99server/_default.cfg +++ b/lgsm/config-default/config-lgsm/ut99server/_default.cfg @@ -13,7 +13,11 @@ defaultmap="DM-Deck16][" ip="0.0.0.0" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters -startparameters="server ${defaultmap}.unr ini=${servercfgfullpath}" +startparameters="server ${defaultmap}.unr ini=${servercfgfullpath} -nohomedir" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" #### LinuxGSM Settings #### @@ -103,6 +107,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -161,7 +170,7 @@ glibc="2.1" # Edit with care ## Game Server Directories -systemdir="${serverfiles}/System64" +systemdir="${serverfiles}/System" executabledir="${systemdir}" executable="./ucc-bin" servercfgdir="${systemdir}" diff --git a/lgsm/config-default/config-lgsm/utserver/_default.cfg b/lgsm/config-default/config-lgsm/utserver/_default.cfg index e26b79e6e2..3875d1dd9b 100644 --- a/lgsm/config-default/config-lgsm/utserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/utserver/_default.cfg @@ -19,6 +19,10 @@ timelimit="10" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="UnrealTournament ${defaultmap}?Game=${gametype}?TimeLimit=${timelimit} -port=${port}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/vhserver/_default.cfg b/lgsm/config-default/config-lgsm/vhserver/_default.cfg index a1691b8397..d1b0916fd6 100644 --- a/lgsm/config-default/config-lgsm/vhserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/vhserver/_default.cfg @@ -50,8 +50,15 @@ instanceid="1" worldmodifiers="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters +# -crossplay routes connections through the PlayFab relay so Xbox/Game Pass players can join. +# Steam-only servers joined by direct IP: copy startparameters to your instance config and remove -crossplay. +# https://docs.linuxgsm.com/game-servers/valheim#crossplay startparameters="-name '${servername}' -password ${serverpassword} -port ${port} -world ${worldname} -public ${public} -savedir '${savedir}' -saveinterval ${saveinterval} -backups ${backups} -backupshort ${backupshort} -backuplong ${backuplong} -crossplay -instanceid ${instanceid} ${logFile:+ -logFile '${logFile}'} ${worldmodifiers:+ ${worldmodifiers}}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -140,6 +147,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/vintsserver/_default.cfg b/lgsm/config-default/config-lgsm/vintsserver/_default.cfg index 47dcfb3d03..2dcf839049 100644 --- a/lgsm/config-default/config-lgsm/vintsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/vintsserver/_default.cfg @@ -11,6 +11,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="--dataPath ${servercfgdir}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + ## Release Settings | https://docs.linuxgsm.com/game-servers/vintagestory#release-settings # Branch (stable|unstable|) branch="stable" @@ -103,6 +107,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/vpmcserver/_default.cfg b/lgsm/config-default/config-lgsm/vpmcserver/_default.cfg index 67715860f8..90678422fd 100644 --- a/lgsm/config-default/config-lgsm/vpmcserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/vpmcserver/_default.cfg @@ -14,6 +14,10 @@ javaram="1024" # -Xmx$1024M ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + ## Release Settings | https://docs.linuxgsm.com/game-servers/minecraft#release-settings # Version (latest|3.1.1) mcversion="latest" @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/vsserver/_default.cfg b/lgsm/config-default/config-lgsm/vsserver/_default.cfg index d640347acc..2944bd1586 100644 --- a/lgsm/config-default/config-lgsm/vsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/vsserver/_default.cfg @@ -18,6 +18,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game vs -strictportbind +ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -114,6 +123,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/config-default/config-lgsm/wetserver/_default.cfg b/lgsm/config-default/config-lgsm/wetserver/_default.cfg index 819390dc04..f8f4c79e47 100644 --- a/lgsm/config-default/config-lgsm/wetserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/wetserver/_default.cfg @@ -9,7 +9,11 @@ #### Game Server Settings #### ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters -startparameters="+set net_strict 1 +set fs_homepath ${serverfiles} +exec ${servercfg}" +startparameters="+set sv_punkbuster 0 +set net_strict 1 +set fs_homepath ${serverfiles} +exec ${servercfg}" + +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" #### LinuxGSM Settings #### @@ -99,6 +103,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" @@ -145,7 +154,7 @@ querytype="protocol-quake3" ## Console type consoleverbose="yes" -consoleinteract="no" +consoleinteract="yes" ## Game Server Details # Do not edit diff --git a/lgsm/config-default/config-lgsm/wfserver/_default.cfg b/lgsm/config-default/config-lgsm/wfserver/_default.cfg index ab0c88e305..d450eb0b2f 100644 --- a/lgsm/config-default/config-lgsm/wfserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/wfserver/_default.cfg @@ -16,6 +16,10 @@ httpport="44444" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="+exec ${servercfg} +sv_http_ip ${ip} +set sv_http_port ${httpport} +sv_ip ${ip} +sv_port ${port}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -104,6 +108,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/wmcserver/_default.cfg b/lgsm/config-default/config-lgsm/wmcserver/_default.cfg index 4b2a258065..b130a535bc 100644 --- a/lgsm/config-default/config-lgsm/wmcserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/wmcserver/_default.cfg @@ -14,6 +14,10 @@ javaram="1024" # -Xmx$1024M ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="nogui" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + ## Release Settings | https://docs.linuxgsm.com/game-servers/minecraft#release-settings # Version (latest|1.16.5) mcversion="latest" @@ -106,6 +110,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/wurmserver/_default.cfg b/lgsm/config-default/config-lgsm/wurmserver/_default.cfg index a57da3c364..f1053e514e 100644 --- a/lgsm/config-default/config-lgsm/wurmserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/wurmserver/_default.cfg @@ -55,6 +55,10 @@ queryport="27016" # Parameters are edited in the game server config file. startparameters="start=${gamemode} adminpwd='${adminpassword}' epicsettings='${epicsettings}' externalport='${port}' homeserver='${homeserver}' homekingdom='${homekingdom}' loginserver='${loginserver}' maxplayers='${maxplayers}' queryport='${queryport}' rmiport='${rmiport}' rmiregport='${rmiregport}' servername='${servername}' serverpassword='${serverpassword}' ip='${ip}'" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -143,6 +147,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" diff --git a/lgsm/config-default/config-lgsm/xntserver/_default.cfg b/lgsm/config-default/config-lgsm/xntserver/_default.cfg index da371512e9..76949d7560 100644 --- a/lgsm/config-default/config-lgsm/xntserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/xntserver/_default.cfg @@ -13,6 +13,10 @@ ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-userdir ${systemdir}/${selfname}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -97,6 +101,15 @@ telegramthreadid="" telegramsilentnotification="false" curlcustomstring="" +## Stop | https://docs.linuxgsm.com/commands/start-stop-restart +stoponlyifnoplayers="off" +stoponlyifnoplayersallcommands="on" + +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Backup | https://docs.linuxgsm.com/commands/backup maxbackups="4" maxbackupdays="30" diff --git a/lgsm/config-default/config-lgsm/zmrserver/_default.cfg b/lgsm/config-default/config-lgsm/zmrserver/_default.cfg index 262487bdba..c9ad34904f 100644 --- a/lgsm/config-default/config-lgsm/zmrserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/zmrserver/_default.cfg @@ -19,6 +19,10 @@ maxplayers="16" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game zombie_master_reborn -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -107,6 +111,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -115,6 +124,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" @@ -136,7 +150,7 @@ sleeptime="0.5" appid="244310" # Source 2013 SDK steamcmdforcewindows="no" # SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch -branch="" +branch="previous2021" betapassword="" # Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server steammaster="true" diff --git a/lgsm/config-default/config-lgsm/zpsserver/_default.cfg b/lgsm/config-default/config-lgsm/zpsserver/_default.cfg index 456a617659..70eb4b7b25 100644 --- a/lgsm/config-default/config-lgsm/zpsserver/_default.cfg +++ b/lgsm/config-default/config-lgsm/zpsserver/_default.cfg @@ -24,6 +24,10 @@ gslt="" ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters startparameters="-game zps -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters +# Added to the end of startparameters. +extraparams="" + #### LinuxGSM Settings #### ## LinuxGSM Stats @@ -112,6 +116,11 @@ curlcustomstring="" stoponlyifnoplayers="off" stoponlyifnoplayersallcommands="on" +## Player Warnings | https://docs.linuxgsm.com/features/player-warnings +# Minutes to warn players in-game before a stop, restart or update. 0 to disable. +# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes. +warnplayerstimer="0" + ## Updating | https://docs.linuxgsm.com/commands/update updateonstart="off" @@ -120,6 +129,11 @@ maxbackups="4" maxbackupdays="30" stoponbackup="on" +## Fastdl | https://docs.linuxgsm.com/commands/fastdl +# Paths to leave out of Fastdl, relative to the Fastdl directory and separated by spaces. +# e.g. "maps/workshop/ sound/music/" +fastdlexclude="maps/workshop/" + ## Logging | https://docs.linuxgsm.com/features/logging consolelogging="on" logdays="7" diff --git a/lgsm/data/almalinux-8.csv b/lgsm/data/almalinux-8.csv index e02ca7858f..df94f531d3 100644 --- a/lgsm/data/almalinux-8.csv +++ b/lgsm/data/almalinux-8.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python36,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl,openssl-libs -ats +ats,libatomic av bb bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw -cod,compat-libstdc++-33.i686 -cod2,compat-libstdc++-33.i686 +cod +cod2 cod4 -coduo,compat-libstdc++-33.i686 +coduo codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -45,32 +48,37 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d l4d2 +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib mc,java-21-openjdk mcb,libnsl mcv mh -mohaa,compat-libstdc++-33.i686 +mohaa mta,ncurses-compat-libs,libxml2 nd nec @@ -80,12 +88,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar,libicu,openssl-libs,zlib opfor pc pc2 pmc,java-21-openjdk pvkii -pvr,libcxx +pvr,libatomic pw pz,java-11-openjdk rng-tools q2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-11-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/almalinux-9.csv b/lgsm/data/almalinux-9.csv index 5a6d996e76..a3cf265fa3 100644 --- a/lgsm/data/almalinux-9.csv +++ b/lgsm/data/almalinux-9.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python3,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl,openssl-libs -ats +ats,libatomic av bb bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw -cod,compat-libstdc++-33.i686 -cod2,compat-libstdc++-33.i686 +cod +cod2 cod4 -coduo,compat-libstdc++-33.i686 +coduo codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -45,32 +48,37 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt,java-25-openjdk hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d l4d2 -mc,java-21-openjdk +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib +mc,java-25-openjdk mcb,libnsl mcv mh -mohaa,compat-libstdc++-33.i686 +mohaa mta,ncurses-compat-libs,libxml2 nd nec @@ -80,12 +88,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar,libicu,openssl-libs,zlib opfor pc pc2 -pmc,java-21-openjdk +pmc,java-25-openjdk pvkii -pvr,libcxx +pvr,libatomic pw pz,java-21-openjdk rng-tools q2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-21-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/centos-7.csv b/lgsm/data/centos-7.csv index c5632722e1..a08769763a 100644 --- a/lgsm/data/centos-7.csv +++ b/lgsm/data/centos-7.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python3,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,19 +6,21 @@ ahl2 ark arma3 armar,libcurl,openssl11-libs -ats +ats,libatomic av bb bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw cod,compat-libstdc++-33.i686 @@ -28,10 +30,11 @@ coduo,compat-libstdc++-33.i686 codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -45,27 +48,32 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d l4d2 +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib mc,java-21-openjdk mcb,libnsl mcv @@ -80,12 +88,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar opfor pc pc2 pmc,java-11-openjdk pvkii -pvr,libcxx +pvr,libatomic pw pz,java-11-openjdk rng-tools q2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-11-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/centos-8.csv b/lgsm/data/centos-8.csv index 0b0b766d04..5c466bd2b8 100644 --- a/lgsm/data/centos-8.csv +++ b/lgsm/data/centos-8.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python36,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl,openssl-libs -ats +ats,libatomic av bb bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw -cod,compat-libstdc++-33.i686 -cod2,compat-libstdc++-33.i686 +cod +cod2 cod4 -coduo,compat-libstdc++-33.i686 +coduo codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -45,32 +48,37 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d l4d2 +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib mc,java-21-openjdk mcb,libnsl mcv mh -mohaa,compat-libstdc++-33.i686 +mohaa mta,ncurses-compat-libs,libxml2 nd nec @@ -80,12 +88,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar opfor pc pc2 pmc,java-17-openjdk pvkii -pvr,libcxx +pvr,libatomic pw pz,java-11-openjdk rng-tools q2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-11-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/centos-9.csv b/lgsm/data/centos-9.csv index fd9c0fa39e..cba4326bc3 100644 --- a/lgsm/data/centos-9.csv +++ b/lgsm/data/centos-9.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python3,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl,openssl-libs -ats +ats,libatomic av bb bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw -cod,compat-libstdc++-33.i686 -cod2,compat-libstdc++-33.i686 +cod +cod2 cod4 -coduo,compat-libstdc++-33.i686 +coduo codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -45,32 +48,37 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt,java-25-openjdk hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d l4d2 -mc,java-17-openjdk +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib +mc,java-25-openjdk mcb,libnsl mcv mh -mohaa,compat-libstdc++-33.i686 +mohaa mta,ncurses-compat-libs,libxml2 nd nec @@ -80,12 +88,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar opfor pc pc2 -pmc,java-17-openjdk +pmc,java-25-openjdk pvkii -pvr,libcxx +pvr,libatomic pw pz,java-21-openjdk rng-tools q2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-21-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/debian-10.csv b/lgsm/data/debian-10.csv index 5b8d73a06a..e79ad4bf15 100644 --- a/lgsm/data/debian-10.csv +++ b/lgsm/data/debian-10.csv @@ -1,23 +1,25 @@ ac ahl ahl2 -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -27,10 +29,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu63 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -44,27 +47,32 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-11-jre mcb mcv @@ -79,6 +87,7 @@ ns2,speex,libtbb2 ns2c,speex:i386,libtbb2 ohd onset,libmariadb-dev +orar opfor pc pc2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-11-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/debian-11.csv b/lgsm/data/debian-11.csv index adba97d278..bfdbd0647d 100644 --- a/lgsm/data/debian-11.csv +++ b/lgsm/data/debian-11.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,19 +6,21 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -28,10 +30,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu67 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -45,27 +48,32 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-17-jre mcb mcv @@ -80,6 +88,7 @@ ns2,speex,libtbb2 ns2c,speex:i386,libtbb2 ohd onset,libmariadb-dev +orar,libicu67,libssl1.1,zlib1g opfor pc pc2 @@ -96,18 +105,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-17-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/debian-12.csv b/lgsm/data/debian-12.csv index 40e325b6c3..0bcf5e8d7a 100644 --- a/lgsm/data/debian-12.csv +++ b/lgsm/data/debian-12.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,19 +6,21 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -28,10 +30,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu72 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -45,27 +48,32 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-17-jre mcb mcv @@ -80,6 +88,7 @@ ns2,speex,libtbb12 ns2c,speex:i386,libtbb12 ohd onset,libmariadb-dev +orar,libicu72,libssl3,zlib1g opfor pc pc2 @@ -96,24 +105,25 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-17-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad st,libxml2-utils stn -sven,libssl3:i386,zlib1g:i386 +sven,zlib1g:i386 terraria tf tf2,libcurl4-gnutls-dev:i386 diff --git a/lgsm/data/debian-13.csv b/lgsm/data/debian-13.csv index 94c6cf1ae8..e909a12669 100644 --- a/lgsm/data/debian-13.csv +++ b/lgsm/data/debian-13.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386 -bfv,libncurses5:i386,libstdc++5:i386 -bmdm,libncurses5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 +bmdm bo bs -bt,libicu-dev,dos2unix,libxml2 +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw -cod,libstdc++5:i386 -cod2,libstdc++5:i386 +cod,libc6:i386 +cod2,libc6:i386 cod4 -coduo,libstdc++5:i386 +coduo,libc6:i386 codwaw col cs -cs2 +cs2,libicu76 cscz csgo css +cswon,libc6:i386 ct dab dayz @@ -45,33 +48,38 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt,openjdk-25-jre hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4t64,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-25-jre mcb mcv mh -mohaa,libstdc++5:i386 -mta,libncursesw6,libxml2 +mohaa,libc6:i386 +mta,libncursesw6,libxml2-utils nd nec nmrih @@ -80,6 +88,7 @@ ns2,speex,libtbb12 ns2c,speex:i386,libtbb12 ohd onset,libmariadb-dev +orar,libicu76,libssl3t64,zlib1g opfor pc pc2 @@ -96,24 +105,25 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-25-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete,libicu76 -scpslsm,mono-complete -sdtd,telnet,expect,libxml2 +sdtd,libxml2-utils sf sfc -sm,telnet,expect +sm sof2 sol squad -st,libxml2 +st,libxml2-utils stn -sven,libssl3:i386,zlib1g:i386 +sven,zlib1g:i386 terraria tf tf2,libcurl4-gnutls-dev:i386 diff --git a/lgsm/data/debian-9.csv b/lgsm/data/debian-9.csv index c0e990961f..088ec5a0fa 100644 --- a/lgsm/data/debian-9.csv +++ b/lgsm/data/debian-9.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,python3,tar,tmux,unzip,util-linux,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,wget,xz-utils steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,19 +6,21 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -28,10 +30,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu57 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -45,27 +48,32 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-8-jre mcb mcv @@ -80,6 +88,7 @@ ns2,speex,libtbb2 ns2c,speex:i386,libtbb2 ohd onset,libmariadb-dev +orar opfor pc pc2 @@ -96,18 +105,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-8-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/gameicons/bfe-icon.png b/lgsm/data/gameicons/bfe-icon.png new file mode 100644 index 0000000000..b6a660b6c4 Binary files /dev/null and b/lgsm/data/gameicons/bfe-icon.png differ diff --git a/lgsm/data/gameicons/ce-icon.png b/lgsm/data/gameicons/ce-icon.png new file mode 100644 index 0000000000..64b866e67c Binary files /dev/null and b/lgsm/data/gameicons/ce-icon.png differ diff --git a/lgsm/data/gameicons/cswon-icon.png b/lgsm/data/gameicons/cswon-icon.png new file mode 100644 index 0000000000..5e61337e05 Binary files /dev/null and b/lgsm/data/gameicons/cswon-icon.png differ diff --git a/lgsm/data/gameicons/fivem-icon.png b/lgsm/data/gameicons/fivem-icon.png new file mode 100644 index 0000000000..db832a78ec Binary files /dev/null and b/lgsm/data/gameicons/fivem-icon.png differ diff --git a/lgsm/data/gameicons/hlwon-icon.png b/lgsm/data/gameicons/hlwon-icon.png new file mode 100644 index 0000000000..2a97796401 Binary files /dev/null and b/lgsm/data/gameicons/hlwon-icon.png differ diff --git a/lgsm/data/gameicons/hyt-icon.png b/lgsm/data/gameicons/hyt-icon.png new file mode 100644 index 0000000000..3942ea6161 Binary files /dev/null and b/lgsm/data/gameicons/hyt-icon.png differ diff --git a/lgsm/data/gameicons/jk3-icon.png b/lgsm/data/gameicons/jk3-icon.png new file mode 100644 index 0000000000..8c480a205e Binary files /dev/null and b/lgsm/data/gameicons/jk3-icon.png differ diff --git a/lgsm/data/gameicons/luanti-icon.png b/lgsm/data/gameicons/luanti-icon.png new file mode 100644 index 0000000000..334e2f6d61 Binary files /dev/null and b/lgsm/data/gameicons/luanti-icon.png differ diff --git a/lgsm/data/gameicons/orar-icon.png b/lgsm/data/gameicons/orar-icon.png new file mode 100644 index 0000000000..f2562b3810 Binary files /dev/null and b/lgsm/data/gameicons/orar-icon.png differ diff --git a/lgsm/data/gameicons/rsdw-icon.png b/lgsm/data/gameicons/rsdw-icon.png new file mode 100644 index 0000000000..0a15bc3ed0 Binary files /dev/null and b/lgsm/data/gameicons/rsdw-icon.png differ diff --git a/lgsm/data/gameicons/rwr-icon.png b/lgsm/data/gameicons/rwr-icon.png new file mode 100644 index 0000000000..9e92ba1d7b Binary files /dev/null and b/lgsm/data/gameicons/rwr-icon.png differ diff --git a/lgsm/data/gameicons/scpslsm-icon.png b/lgsm/data/gameicons/scpslsm-icon.png deleted file mode 100644 index 2872a78412..0000000000 Binary files a/lgsm/data/gameicons/scpslsm-icon.png and /dev/null differ diff --git a/lgsm/data/gameicons/sm-icon.png b/lgsm/data/gameicons/sm-icon.png index 7948e002d6..70eb766c98 100644 Binary files a/lgsm/data/gameicons/sm-icon.png and b/lgsm/data/gameicons/sm-icon.png differ diff --git a/lgsm/data/rhel-7.csv b/lgsm/data/rhel-7.csv index d7801771c0..4da812078c 100644 --- a/lgsm/data/rhel-7.csv +++ b/lgsm/data/rhel-7.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python36,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,20 +6,23 @@ ahl2 ark arma3 armar,libcurl,openssl11-libs -ats +ats,libatomic av bb +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib pw bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw cod,compat-libstdc++-33.i686 @@ -29,10 +32,11 @@ coduo,compat-libstdc++-33.i686 codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -46,23 +50,27 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d @@ -81,12 +89,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar opfor pc pc2 pmc,java-11-openjdk pvkii -pvr,libcxx +pvr,libatomic pz,java-11-openjdk rng-tools q2 q3 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-11-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/rhel-8.csv b/lgsm/data/rhel-8.csv index d654242652..f1940f74ab 100644 --- a/lgsm/data/rhel-8.csv +++ b/lgsm/data/rhel-8.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python36,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl,openssl-libs -ats +ats,libatomic av bb bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw -cod,compat-libstdc++-33.i686 -cod2,compat-libstdc++-33.i686 +cod +cod2 cod4 -coduo,compat-libstdc++-33.i686 +coduo codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -45,32 +48,37 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d l4d2 +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib mc,java-21-openjdk mcb,libnsl mcv mh -mohaa,compat-libstdc++-33.i686 +mohaa mta,ncurses-compat-libs,libxml2 nd nec @@ -80,12 +88,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar,libicu,openssl-libs,zlib opfor pc pc2 pmc,java-21-openjdk pvkii -pvr,libcxx +pvr,libatomic pw pz,java-21-openjdk rng-tools q2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-21-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/rhel-9.csv b/lgsm/data/rhel-9.csv index 5a6d996e76..a3cf265fa3 100644 --- a/lgsm/data/rhel-9.csv +++ b/lgsm/data/rhel-9.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python3,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl,openssl-libs -ats +ats,libatomic av bb bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw -cod,compat-libstdc++-33.i686 -cod2,compat-libstdc++-33.i686 +cod +cod2 cod4 -coduo,compat-libstdc++-33.i686 +coduo codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -45,32 +48,37 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt,java-25-openjdk hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d l4d2 -mc,java-21-openjdk +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib +mc,java-25-openjdk mcb,libnsl mcv mh -mohaa,compat-libstdc++-33.i686 +mohaa mta,ncurses-compat-libs,libxml2 nd nec @@ -80,12 +88,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar,libicu,openssl-libs,zlib opfor pc pc2 -pmc,java-21-openjdk +pmc,java-25-openjdk pvkii -pvr,libcxx +pvr,libatomic pw pz,java-21-openjdk rng-tools q2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-21-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/rocky-8.csv b/lgsm/data/rocky-8.csv index d654242652..f1940f74ab 100644 --- a/lgsm/data/rocky-8.csv +++ b/lgsm/data/rocky-8.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python36,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl,openssl-libs -ats +ats,libatomic av bb bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw -cod,compat-libstdc++-33.i686 -cod2,compat-libstdc++-33.i686 +cod +cod2 cod4 -coduo,compat-libstdc++-33.i686 +coduo codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -45,32 +48,37 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d l4d2 +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib mc,java-21-openjdk mcb,libnsl mcv mh -mohaa,compat-libstdc++-33.i686 +mohaa mta,ncurses-compat-libs,libxml2 nd nec @@ -80,12 +88,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar,libicu,openssl-libs,zlib opfor pc pc2 pmc,java-21-openjdk pvkii -pvr,libcxx +pvr,libatomic pw pz,java-21-openjdk rng-tools q2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-21-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/rocky-9.csv b/lgsm/data/rocky-9.csv index 5a6d996e76..a3cf265fa3 100644 --- a/lgsm/data/rocky-9.csv +++ b/lgsm/data/rocky-9.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,python3,tar,tmux,unzip,util-linux,wget,xz +all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz steamcmd,glibc.i686,libstdc++.i686 ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl,openssl-libs -ats +ats,libatomic av bb bb2,libcurl.i686 bd bf1942,ncurses-libs.i686 -bfv,compat-libstdc++-33.i686,glibc.i686 +bfe +bfv,glibc.i686 bmdm,ncurses-libs.i686 bo bs -bt,libicu,dos2unix,libxml2 +bt,dos2unix,libxml2 btl cc +ce ck,xorg-x11-server-Xvfb cmw -cod,compat-libstdc++-33.i686 -cod2,compat-libstdc++-33.i686 +cod +cod2 cod4 -coduo,compat-libstdc++-33.i686 +coduo codwaw col cs -cs2 +cs2,libicu cscz csgo css,ncurses-libs.i686 +cswon ct dab dayz @@ -45,32 +48,37 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic fctr +fivem fof gmod,ncurses-libs.i686 hcu hl2dm hldm hldms +hlwon hw,zlib-devel +hyt,java-25-openjdk hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic jk2 +jk3,libstdc++,zlib kf kf2 l4d l4d2 -mc,java-21-openjdk +luanti,libcurl,libstdc++,libzstd,ncurses-libs,sqlite-libs,zlib +mc,java-25-openjdk mcb,libnsl mcv mh -mohaa,compat-libstdc++-33.i686 +mohaa mta,ncurses-compat-libs,libxml2 nd nec @@ -80,12 +88,13 @@ ns2,speex,tbb ns2c,speex.i686,tbb.i686 ohd onset,mariadb-connector-c +orar,libicu,openssl-libs,zlib opfor pc pc2 -pmc,java-21-openjdk +pmc,java-25-openjdk pvkii -pvr,libcxx +pvr,libatomic pw pz,java-21-openjdk rng-tools q2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,zlib-devel rw,java-21-openjdk +rwr,libgpg-error.i686,libX11.i686,libXext.i686,zlib.i686 samp sb sbots scpsl -scpslsm -sdtd,telnet,expect,libxml2 +sdtd,libxml2 sf sfc,ncurses-libs.i686 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/serverlist.csv b/lgsm/data/serverlist.csv index 3ddc013c31..295cc60a3f 100644 --- a/lgsm/data/serverlist.csv +++ b/lgsm/data/serverlist.csv @@ -1,141 +1,151 @@ shortname,gameservername,gamename,os -ac,acserver,Assetto Corsa,ubuntu-24.04 -ahl,ahlserver,Action Half-Life,ubuntu-24.04 -ahl2,ahl2server,Action: Source,ubuntu-24.04 -ark,arkserver,ARK: Survival Evolved,ubuntu-24.04 -arma3,arma3server,ARMA 3,ubuntu-24.04 -armar,armarserver,Arma Reforger,ubuntu-24.04 -ats,atsserver,American Truck Simulator,ubuntu-24.04 -av,avserver,Avorion,ubuntu-24.04 -bb,bbserver,BrainBread,ubuntu-24.04 -bb2,bb2server,BrainBread 2,ubuntu-24.04 -bd,bdserver,Base Defense,ubuntu-24.04 -bf1942,bf1942server,Battlefield 1942,ubuntu-22.04 -bfv,bfvserver,Battlefield: Vietnam,ubuntu-22.04 -bmdm,bmdmserver,Black Mesa: Deathmatch,ubuntu-24.04 -bo,boserver,Ballistic Overkill,ubuntu-24.04 -bs,bsserver,Blade Symphony,ubuntu-24.04 -bt,btserver,Barotrauma,ubuntu-24.04 +ac,acserver,Assetto Corsa,ubuntu-26.04 +ahl,ahlserver,Action Half-Life,ubuntu-26.04 +ahl2,ahl2server,Action: Source,ubuntu-26.04 +ark,arkserver,ARK: Survival Evolved,ubuntu-26.04 +arma3,arma3server,ARMA 3,ubuntu-26.04 +armar,armarserver,Arma Reforger,ubuntu-26.04 +ats,atsserver,American Truck Simulator,ubuntu-26.04 +av,avserver,Avorion,ubuntu-26.04 +bb,bbserver,BrainBread,ubuntu-26.04 +bb2,bb2server,BrainBread 2,ubuntu-26.04 +bd,bdserver,Base Defense,ubuntu-26.04 +bf1942,bf1942server,Battlefield 1942,ubuntu-26.04 +bfe,bfeserver,Battlefront Eternal,ubuntu-26.04 +bfv,bfvserver,Battlefield: Vietnam,ubuntu-26.04 +bmdm,bmdmserver,Black Mesa: Deathmatch,ubuntu-26.04 +bo,boserver,Ballistic Overkill,ubuntu-26.04 +bs,bsserver,Blade Symphony,ubuntu-26.04 +bt,btserver,Barotrauma,ubuntu-26.04 btl,btlserver,BATTALION: Legacy,ubuntu-20.04 -cc,ccserver,Codename CURE,ubuntu-24.04 -ck,ckserver,Core Keeper,ubuntu-24.04 -cmw,cmwserver,Chivalry: Medieval Warfare,ubuntu-24.04 +cc,ccserver,Codename CURE,ubuntu-26.04 +ce,ceserver,Conan Exiles,ubuntu-26.04 +ck,ckserver,Core Keeper,ubuntu-26.04 +cmw,cmwserver,Chivalry: Medieval Warfare,ubuntu-26.04 cod,codserver,Call of Duty,ubuntu-24.04 cod2,cod2server,Call of Duty 2,ubuntu-24.04 -cod4,cod4server,Call of Duty 4,ubuntu-24.04 +cod4,cod4server,Call of Duty 4,ubuntu-26.04 coduo,coduoserver,Call of Duty: United Offensive,ubuntu-24.04 -codwaw,codwawserver,Call of Duty: World at War,ubuntu-24.04 -col,colserver,Colony Survival,ubuntu-24.04 -cs,csserver,Counter-Strike 1.6,ubuntu-24.04 -cs2,cs2server,Counter-Strike 2,ubuntu-24.04 -cscz,csczserver,Counter-Strike: Condition Zero,ubuntu-24.04 -csgo,csgoserver,Counter-Strike: Global Offensive,ubuntu-24.04 -css,cssserver,Counter-Strike: Source,ubuntu-24.04 -ct,ctserver,Craftopia,ubuntu-24.04 -dab,dabserver,Double Action: Boogaloo,ubuntu-24.04 -dayz,dayzserver,DayZ,ubuntu-24.04 -dmc,dmcserver,Deathmatch Classic,ubuntu-24.04 -dod,dodserver,Day of Defeat,ubuntu-24.04 -dodr,dodrserver,Day of Dragons,ubuntu-24.04 -dods,dodsserver,Day of Defeat: Source,ubuntu-24.04 -doi,doiserver,Day of Infamy,ubuntu-24.04 -dst,dstserver,Don't Starve Together,ubuntu-24.04 -dys,dysserver,Dystopia,ubuntu-24.04 -eco,ecoserver,Eco,ubuntu-24.04 -em,emserver,Empires Mod,ubuntu-24.04 -etl,etlserver,ET: Legacy,ubuntu-24.04 -ets2,ets2server,Euro Truck Simulator 2,ubuntu-24.04 -fctr,fctrserver,Factorio,ubuntu-24.04 -fof,fofserver,Fistful of Frags,ubuntu-24.04 -gmod,gmodserver,Garrys Mod,ubuntu-24.04 -hcu,hcuserver,HYPERCHARGE: Unboxed,ubuntu-24.04 -hl2dm,hl2dmserver,Half-Life 2: Deathmatch,ubuntu-24.04 -hldm,hldmserver,Half-Life: Deathmatch,ubuntu-24.04 -hldms,hldmsserver,Half-Life Deathmatch: Source,ubuntu-24.04 -hw,hwserver,Hurtworld,ubuntu-24.04 -hz,hzserver,Humanitz,ubuntu-24.04 -ins,insserver,Insurgency,ubuntu-24.04 -inss,inssserver,Insurgency: Sandstorm,ubuntu-24.04 -ios,iosserver,IOSoccer,ubuntu-24.04 -jbep3,jbep3server,Jabroni Brawl: Episode 3,ubuntu-24.04 -jc2,jc2server,Just Cause 2,ubuntu-24.04 -jc3,jc3server,Just Cause 3,ubuntu-24.04 -jk2,jk2server,Jedi Knight II: Jedi Outcast,ubuntu-24.04 -kf,kfserver,Killing Floor,ubuntu-24.04 -kf2,kf2server,Killing Floor 2,ubuntu-24.04 -l4d,l4dserver,Left 4 Dead,ubuntu-24.04 -l4d2,l4d2server,Left 4 Dead 2,ubuntu-24.04 -mc,mcserver,Minecraft,ubuntu-24.04 -mcb,mcbserver,Minecraft Bedrock,ubuntu-24.04 -mcv,mcvserver,Military Conflict: Vietnam,ubuntu-24.04 -mh,mhserver,MORDHAU,ubuntu-24.04 +codwaw,codwawserver,Call of Duty: World at War,ubuntu-26.04 +col,colserver,Colony Survival,ubuntu-26.04 +cs,csserver,Counter-Strike 1.6,ubuntu-26.04 +cs2,cs2server,Counter-Strike 2,ubuntu-26.04 +cscz,csczserver,Counter-Strike: Condition Zero,ubuntu-26.04 +csgo,csgoserver,Counter-Strike: Global Offensive,ubuntu-26.04 +css,cssserver,Counter-Strike: Source,ubuntu-26.04 +cswon,cswonserver,Counter-Strike: WON2,ubuntu-26.04 +ct,ctserver,Craftopia,ubuntu-26.04 +dab,dabserver,Double Action: Boogaloo,ubuntu-26.04 +dayz,dayzserver,DayZ,ubuntu-26.04 +dmc,dmcserver,Deathmatch Classic,ubuntu-26.04 +dod,dodserver,Day of Defeat,ubuntu-26.04 +dodr,dodrserver,Day of Dragons,ubuntu-26.04 +dods,dodsserver,Day of Defeat: Source,ubuntu-26.04 +doi,doiserver,Day of Infamy,ubuntu-26.04 +dst,dstserver,Don't Starve Together,ubuntu-26.04 +dys,dysserver,Dystopia,ubuntu-26.04 +eco,ecoserver,Eco,ubuntu-26.04 +em,emserver,Empires Mod,ubuntu-26.04 +etl,etlserver,ET: Legacy,ubuntu-26.04 +ets2,ets2server,Euro Truck Simulator 2,ubuntu-26.04 +fctr,fctrserver,Factorio,ubuntu-26.04 +fivem,fivemserver,FiveM,ubuntu-26.04 +fof,fofserver,Fistful of Frags,ubuntu-26.04 +gmod,gmodserver,Garrys Mod,ubuntu-26.04 +hcu,hcuserver,HYPERCHARGE: Unboxed,ubuntu-26.04 +hl2dm,hl2dmserver,Half-Life 2: Deathmatch,ubuntu-26.04 +hldm,hldmserver,Half-Life: Deathmatch,ubuntu-26.04 +hldms,hldmsserver,Half-Life Deathmatch: Source,ubuntu-26.04 +hlwon,hlwonserver,Half-Life: WON2,ubuntu-26.04 +hw,hwserver,Hurtworld,ubuntu-26.04 +hyt,hytserver,Hytale,ubuntu-26.04 +hz,hzserver,Humanitz,ubuntu-26.04 +ins,insserver,Insurgency,ubuntu-26.04 +inss,inssserver,Insurgency: Sandstorm,ubuntu-26.04 +ios,iosserver,IOSoccer,ubuntu-26.04 +jbep3,jbep3server,Jabroni Brawl: Episode 3,ubuntu-26.04 +jc2,jc2server,Just Cause 2,ubuntu-26.04 +jc3,jc3server,Just Cause 3,ubuntu-26.04 +jk2,jk2server,Jedi Knight II: Jedi Outcast,ubuntu-26.04 +jk3,jk3server,Jedi Knight: Jedi Academy,ubuntu-26.04 +kf,kfserver,Killing Floor,ubuntu-26.04 +kf2,kf2server,Killing Floor 2,ubuntu-26.04 +l4d,l4dserver,Left 4 Dead,ubuntu-26.04 +l4d2,l4d2server,Left 4 Dead 2,ubuntu-26.04 +luanti,luantiserver,Luanti,ubuntu-26.04 +mc,mcserver,Minecraft,ubuntu-26.04 +mcb,mcbserver,Minecraft Bedrock,ubuntu-26.04 +mcv,mcvserver,Military Conflict: Vietnam,ubuntu-26.04 +mh,mhserver,MORDHAU,ubuntu-26.04 mohaa,mohaaserver,Medal of Honor: Allied Assault,ubuntu-24.04 -mta,mtaserver,Multi Theft Auto,ubuntu-24.04 -nd,ndserver,Nuclear Dawn,ubuntu-24.04 -nec,necserver,Necesse,ubuntu-24.04 -nmrih,nmrihserver,No More Room in Hell,ubuntu-24.04 -ns,nsserver,Natural Selection,ubuntu-24.04 -ns2,ns2server,Natural Selection 2,ubuntu-24.04 -ns2c,ns2cserver,NS2: Combat,ubuntu-24.04 -ohd,ohdserver,Operation: Harsh Doorstop,ubuntu-24.04 +mta,mtaserver,Multi Theft Auto,ubuntu-26.04 +nd,ndserver,Nuclear Dawn,ubuntu-26.04 +nec,necserver,Necesse,ubuntu-26.04 +nmrih,nmrihserver,No More Room in Hell,ubuntu-26.04 +ns,nsserver,Natural Selection,ubuntu-26.04 +ns2,ns2server,Natural Selection 2,ubuntu-26.04 +ns2c,ns2cserver,NS2: Combat,ubuntu-26.04 +ohd,ohdserver,Operation: Harsh Doorstop,ubuntu-26.04 onset,onsetserver,Onset,ubuntu-20.04 -opfor,opforserver,Opposing Force,ubuntu-24.04 -pc,pcserver,Project Cars,ubuntu-24.04 -pc2,pc2server,Project Cars 2,ubuntu-24.04 -pmc,pmcserver,PaperMC,ubuntu-24.04 -pvkii,pvkiiserver,Pirates Vikings & Knights II,ubuntu-24.04 -pvr,pvrserver,Pavlov VR,ubuntu-24.04 -pw,pwserver,Palworld,ubuntu-24.04 -pz,pzserver,Project Zomboid,ubuntu-24.04 -q2,q2server,Quake 2,ubuntu-24.04 -q3,q3server,Quake 3: Arena,ubuntu-24.04 -q4,q4server,Quake 4,ubuntu-24.04 -ql,qlserver,Quake Live,ubuntu-24.04 -qw,qwserver,Quake World,ubuntu-24.04 -ricochet,ricochetserver,Ricochet,ubuntu-24.04 -ro,roserver,Red Orchestra: Ostfront 41-45,ubuntu-24.04 -rtcw,rtcwserver,Return to Castle Wolfenstein,ubuntu-24.04 -rust,rustserver,Rust,ubuntu-24.04 -rw,rwserver,Rising World,ubuntu-24.04 -samp,sampserver,San Andreas Multiplayer,ubuntu-24.04 -sb,sbserver,Starbound,ubuntu-24.04 -sbots,sbotsserver,StickyBots,ubuntu-24.04 -scpsl,scpslserver,SCP: Secret Laboratory,ubuntu-24.04 -scpslsm,scpslsmserver,SCP: Secret Laboratory ServerMod,ubuntu-24.04 -sdtd,sdtdserver,7 Days to Die,ubuntu-24.04 -sf,sfserver,Satisfactory,ubuntu-24.04 -sfc,sfcserver,SourceForts Classic,ubuntu-24.04 -sm,smserver,Soulmask,ubuntu-24.04 -sof2,sof2server,Soldier Of Fortune 2: Gold Edition,ubuntu-24.04 -sol,solserver,Soldat,ubuntu-24.04 -squad,squadserver,Squad,ubuntu-24.04 -squad44,squad44server,Squad 44,ubuntu-24.04 -st,stserver,Stationeers,ubuntu-24.04 -stn,stnserver,Survive the Nights,ubuntu-24.04 -sven,svenserver,Sven Co-op,ubuntu-24.04 -terraria,terrariaserver,Terraria,ubuntu-24.04 -tf,tfserver,The Front,ubuntu-24.04 -tf2,tf2server,Team Fortress 2,ubuntu-24.04 -tf2c,tf2cserver,Team Fortress 2 Classified,ubuntu-24.04 -tfc,tfcserver,Team Fortress Classic,ubuntu-24.04 -ti,tiserver,The Isle,ubuntu-24.04 -ts,tsserver,The Specialists,ubuntu-24.04 -ts3,ts3server,Teamspeak 3,ubuntu-24.04 -tu,tuserver,Tower Unite,ubuntu-24.04 -tw,twserver,Teeworlds,ubuntu-24.04 -unt,untserver,Unturned,ubuntu-24.04 -ut,utserver,Unreal Tournament,ubuntu-24.04 -ut2k4,ut2k4server,Unreal Tournament 2004,ubuntu-24.04 -ut3,ut3server,Unreal Tournament 3,ubuntu-24.04 -ut99,ut99server,Unreal Tournament 99,ubuntu-24.04 -vh,vhserver,Valheim,ubuntu-24.04 -vints,vintsserver,Vintage Story,ubuntu-24.04 -vpmc,vpmcserver,Velocity Proxy MC,ubuntu-24.04 -vs,vsserver,Vampire Slayer,ubuntu-24.04 -wet,wetserver,Wolfenstein: Enemy Territory,ubuntu-24.04 -wf,wfserver,Warfork,ubuntu-24.04 -wmc,wmcserver,WaterfallMC,ubuntu-24.04 -wurm,wurmserver,Wurm Unlimited,ubuntu-24.04 -xnt,xntserver,Xonotic,ubuntu-24.04 -zmr,zmrserver,Zombie Master: Reborn,ubuntu-24.04 -zps,zpsserver,Zombie Panic! Source,ubuntu-24.04 +orar,orarserver,OpenRA: Red Alert,ubuntu-24.04 +opfor,opforserver,Opposing Force,ubuntu-26.04 +pc,pcserver,Project Cars,ubuntu-26.04 +pc2,pc2server,Project Cars 2,ubuntu-26.04 +pmc,pmcserver,PaperMC,ubuntu-26.04 +pvkii,pvkiiserver,Pirates Vikings & Knights II,ubuntu-26.04 +pvr,pvrserver,Pavlov VR,ubuntu-26.04 +pw,pwserver,Palworld,ubuntu-26.04 +pz,pzserver,Project Zomboid,ubuntu-26.04 +q2,q2server,Quake 2,ubuntu-26.04 +q3,q3server,Quake 3: Arena,ubuntu-26.04 +q4,q4server,Quake 4,ubuntu-26.04 +ql,qlserver,Quake Live,ubuntu-26.04 +qw,qwserver,Quake World,ubuntu-26.04 +ricochet,ricochetserver,Ricochet,ubuntu-26.04 +ro,roserver,Red Orchestra: Ostfront 41-45,ubuntu-26.04 +rsdw,rsdwserver,RuneScape: Dragonwilds,ubuntu-26.04 +rtcw,rtcwserver,Return to Castle Wolfenstein,ubuntu-26.04 +rust,rustserver,Rust,ubuntu-26.04 +rw,rwserver,Rising World,ubuntu-26.04 +rwr,rwrserver,Running With Rifles,ubuntu-26.04 +samp,sampserver,San Andreas Multiplayer,ubuntu-26.04 +sb,sbserver,Starbound,ubuntu-26.04 +sbots,sbotsserver,StickyBots,ubuntu-26.04 +scpsl,scpslserver,SCP: Secret Laboratory,ubuntu-26.04 +sdtd,sdtdserver,7 Days to Die,ubuntu-26.04 +sf,sfserver,Satisfactory,ubuntu-26.04 +sfc,sfcserver,SourceForts Classic,ubuntu-26.04 +sm,smserver,Soulmask,ubuntu-26.04 +sof2,sof2server,Soldier Of Fortune 2: Gold Edition,ubuntu-26.04 +sol,solserver,Soldat,ubuntu-26.04 +squad,squadserver,Squad,ubuntu-26.04 +squad44,squad44server,Squad 44,ubuntu-26.04 +st,stserver,Stationeers,ubuntu-26.04 +stn,stnserver,Survive the Nights,ubuntu-26.04 +sven,svenserver,Sven Co-op,ubuntu-26.04 +terraria,terrariaserver,Terraria,ubuntu-26.04 +tf,tfserver,The Front,ubuntu-26.04 +tf2,tf2server,Team Fortress 2,ubuntu-26.04 +tf2c,tf2cserver,Team Fortress 2 Classified,ubuntu-26.04 +tfc,tfcserver,Team Fortress Classic,ubuntu-26.04 +ti,tiserver,The Isle,ubuntu-26.04 +ts,tsserver,The Specialists,ubuntu-26.04 +ts3,ts3server,Teamspeak 3,ubuntu-26.04 +tu,tuserver,Tower Unite,ubuntu-26.04 +tw,twserver,Teeworlds,ubuntu-26.04 +unt,untserver,Unturned,ubuntu-26.04 +ut,utserver,Unreal Tournament,ubuntu-26.04 +ut2k4,ut2k4server,Unreal Tournament 2004,ubuntu-26.04 +ut3,ut3server,Unreal Tournament 3,ubuntu-26.04 +ut99,ut99server,Unreal Tournament 99,ubuntu-26.04 +vh,vhserver,Valheim,ubuntu-26.04 +vints,vintsserver,Vintage Story,ubuntu-26.04 +vpmc,vpmcserver,Velocity Proxy MC,ubuntu-26.04 +vs,vsserver,Vampire Slayer,ubuntu-26.04 +wet,wetserver,Wolfenstein: Enemy Territory,ubuntu-26.04 +wf,wfserver,Warfork,ubuntu-26.04 +wmc,wmcserver,WaterfallMC,ubuntu-26.04 +wurm,wurmserver,Wurm Unlimited,ubuntu-26.04 +xnt,xntserver,Xonotic,ubuntu-26.04 +zmr,zmrserver,Zombie Master: Reborn,ubuntu-26.04 +zps,zpsserver,Zombie Panic! Source,ubuntu-26.04 diff --git a/lgsm/data/ubuntu-16.04.csv b/lgsm/data/ubuntu-16.04.csv index 24fcf33e23..d8e3e7690f 100644 --- a/lgsm/data/ubuntu-16.04.csv +++ b/lgsm/data/ubuntu-16.04.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,20 +6,23 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g pw bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -29,10 +32,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu55 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -46,23 +50,27 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d @@ -81,6 +89,7 @@ ns2,speex,libtbb2 ns2c,speex:i386,libtbb2 ohd onset,libmariadb-dev +orar opfor pc pc2 @@ -96,18 +105,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-8-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/ubuntu-18.04.csv b/lgsm/data/ubuntu-18.04.csv index b283b629a6..5b21882ab3 100644 --- a/lgsm/data/ubuntu-18.04.csv +++ b/lgsm/data/ubuntu-18.04.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,20 +6,23 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g pw bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -29,10 +32,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu60 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -46,23 +50,27 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d @@ -81,6 +89,7 @@ ns2,speex,libtbb2 ns2c,speex:i386,libtbb2 ohd onset,libmariadb-dev +orar opfor pc pc2 @@ -96,18 +105,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-11-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/ubuntu-20.04.csv b/lgsm/data/ubuntu-20.04.csv index b086d0095b..482d238912 100644 --- a/lgsm/data/ubuntu-20.04.csv +++ b/lgsm/data/ubuntu-20.04.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,19 +6,21 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -28,10 +30,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu66 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -45,27 +48,32 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-21-jre mcb mcv @@ -80,6 +88,7 @@ ns2,speex,libtbb2 ns2c,speex:i386,libtbb2 ohd onset,libmariadb-dev +orar opfor pc pc2 @@ -96,18 +105,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-21-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/ubuntu-22.04.csv b/lgsm/data/ubuntu-22.04.csv index 93bfbd4cf5..ea611d7ee9 100644 --- a/lgsm/data/ubuntu-22.04.csv +++ b/lgsm/data/ubuntu-22.04.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,19 +6,21 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -28,10 +30,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu70 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -45,28 +48,33 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt,openjdk-25-jre hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 -mc,openjdk-21-jre +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g +mc,openjdk-25-jre mcb mcv mh @@ -80,10 +88,11 @@ ns2,speex,libtbb2 ns2c,speex:i386,libtbb2 ohd onset,libmariadb-dev +orar,libicu70,libssl3,zlib1g opfor pc pc2 -pmc,openjdk-21-jre +pmc,openjdk-25-jre squad44 pvkii pvr,libc++1 @@ -96,18 +105,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-21-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/ubuntu-23.04.csv b/lgsm/data/ubuntu-23.04.csv index cb871bde04..9d19c5031b 100644 --- a/lgsm/data/ubuntu-23.04.csv +++ b/lgsm/data/ubuntu-23.04.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,19 +6,21 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -28,10 +30,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu72 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -45,27 +48,32 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-21-jre mcb mcv @@ -80,6 +88,7 @@ ns2,speex,libtbb2 ns2c,speex:i386,libtbb2 ohd onset,libmariadb-dev +orar opfor pc pc2 @@ -96,18 +105,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-21-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/ubuntu-23.10.csv b/lgsm/data/ubuntu-23.10.csv index cb871bde04..9d19c5031b 100644 --- a/lgsm/data/ubuntu-23.10.csv +++ b/lgsm/data/ubuntu-23.10.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,19 +6,21 @@ ahl2 ark arma3 armar,libcurl4 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942,libncurses5:i386,libtinfo5:i386 -bfv,libncurses5:i386,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm,libncurses5:i386 bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -28,10 +30,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu72 cscz csgo css,libtinfo5:i386 +cswon,libc6:i386 ct dab dayz @@ -45,27 +48,32 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod,libtinfo5:i386 hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-21-jre mcb mcv @@ -80,6 +88,7 @@ ns2,speex,libtbb2 ns2c,speex:i386,libtbb2 ohd onset,libmariadb-dev +orar opfor pc pc2 @@ -96,18 +105,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-21-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc,libtinfo5:i386 -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/ubuntu-24.04.csv b/lgsm/data/ubuntu-24.04.csv index 0e010abd69..0c72910a2d 100644 --- a/lgsm/data/ubuntu-24.04.csv +++ b/lgsm/data/ubuntu-24.04.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,19 +6,21 @@ ahl2 ark arma3 armar,libcurl4t64 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942 -bfv,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw cod,libstdc++5:i386 @@ -28,10 +30,11 @@ coduo,libstdc++5:i386 codwaw col cs -cs2 +cs2,libicu74 cscz csgo css +cswon,libc6:i386 ct dab dayz @@ -45,27 +48,32 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt,openjdk-25-jre hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4t64,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-25-jre mcb mcv @@ -80,6 +88,7 @@ ns2,speex ns2c,speex:i386 ohd onset,libmariadb-dev +orar,libicu74,libssl3t64,zlib1g opfor pc pc2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-25-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/data/ubuntu-26.04.csv b/lgsm/data/ubuntu-26.04.csv index 0e010abd69..8822d559d0 100644 --- a/lgsm/data/ubuntu-26.04.csv +++ b/lgsm/data/ubuntu-26.04.csv @@ -1,4 +1,4 @@ -all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils +all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd ac ahl @@ -6,32 +6,35 @@ ahl2 ark arma3 armar,libcurl4t64 -ats +ats,libatomic1 av bb bb2,libcurl4-gnutls-dev:i386 bd -bf1942 -bfv,libstdc++5:i386 +bf1942,libc6:i386 +bfe +bfv,libc6:i386 bmdm bo bs -bt,libicu-dev,dos2unix,libxml2-utils +bt,dos2unix,libxml2-utils btl cc +ce ck,xvfb,libxi6 cmw -cod,libstdc++5:i386 -cod2,libstdc++5:i386 +cod,libc6:i386 +cod2,libc6:i386 cod4 -coduo,libstdc++5:i386 +coduo,libc6:i386 codwaw col cs -cs2 +cs2,libicu78 cscz csgo css +cswon,libc6:i386 ct dab dayz @@ -45,32 +48,37 @@ dys eco,libgdiplus em etl -ets2 +ets2,libatomic1 fctr +fivem fof gmod hcu hl2dm hldm hldms +hlwon,libc6:i386 hw,lib32z1 +hyt,openjdk-25-jre hz ins inss ios jbep3 jc2 -jc3 +jc3,libatomic1 jk2 +jk3,libstdc++6,zlib1g kf kf2 l4d l4d2 +luanti,libcurl4t64,libncursesw6,libsqlite3-0,libstdc++6,libzstd1,zlib1g mc,openjdk-25-jre mcb mcv mh -mohaa,libstdc++5:i386 +mohaa,libc6:i386 mta,libxml2-utils nd nec @@ -80,6 +88,7 @@ ns2,speex ns2c,speex:i386 ohd onset,libmariadb-dev +orar,libicu78,libssl3t64,zlib1g opfor pc pc2 @@ -95,18 +104,19 @@ ql qw ricochet ro +rsdw rtcw rust,lib32z1 rw,openjdk-25-jre +rwr,libgpg-error0:i386,libx11-6:i386,libxext6:i386,zlib1g:i386 samp sb sbots scpsl,mono-complete -scpslsm,mono-complete -sdtd,telnet,expect,libxml2-utils +sdtd,libxml2-utils sf sfc -sm,telnet,expect +sm sof2 sol squad diff --git a/lgsm/modules/alert.sh b/lgsm/modules/alert.sh index b256390df6..c9e9d2ef34 100755 --- a/lgsm/modules/alert.sh +++ b/lgsm/modules/alert.sh @@ -169,6 +169,28 @@ fn_alert_backup() { alertcolourdec="52480" } +fn_alert_backup_postponed() { + fn_script_log_warn "Sending alert: ${selfname} backup postponed for over 24 hours" + alertaction="Backup Postponed" + alertemoji="⏳" + alertsound="1" + alertmessage="${selfname} has not been backed up for over 24 hours as players are online. The backup will run once the server is empty." + # Amber + alertcolourhex="#cd8b00" + alertcolourdec="13470464" +} + +fn_alert_hytale_login() { + fn_script_log_info "Sending alert: ${selfname} needs a Hytale server login" + alertaction="Login Required" + alertemoji="🔑" + alertsound="2" + alertmessage="${selfname} needs a Hytale server login. Open ${hytloginurl} and log in with a Hytale account that owns the game. The code expires in 10 minutes." + # Blue + alertcolourhex="#1e90ff" + alertcolourdec="2003199" +} + fn_alert_permissions() { fn_script_log_info "Sending alert: ${selfname} has permissions issues" alertaction="Checked Permissions" @@ -250,6 +272,10 @@ elif [ "${alert}" == "update-linuxgsm" ]; then fn_alert_update_linuxgsm elif [ "${alert}" == "backup" ]; then fn_alert_backup +elif [ "${alert}" == "backup-postponed" ]; then + fn_alert_backup_postponed +elif [ "${alert}" == "hytale-login" ]; then + fn_alert_hytale_login else fn_print_fail_nl "Missing alert type" fn_script_log_fail "Missing alert type" diff --git a/lgsm/modules/alert_matrix.sh b/lgsm/modules/alert_matrix.sh index 34d226f1f1..8938b8cdd9 100755 --- a/lgsm/modules/alert_matrix.sh +++ b/lgsm/modules/alert_matrix.sh @@ -18,6 +18,8 @@ matrixroomencoded="$(jq -rn --arg room "${matrixroom}" '$room|@uri')" matrixtxnid="$(date +%s%N)" matrixurl="${matrixbase}/_matrix/client/v3/rooms/${matrixroomencoded}/send/m.room.message/${matrixtxnid}" +alerttime="$(date)" + message="${alerttitle} Server Name @@ -33,13 +35,14 @@ Server IP ${alertip}:${port} Server Time -$(date)" +${alerttime}" if [ -n "${querytype}" ]; then + imgsourl="https://ismygameserver.online/${imgsoquerytype}/${alertip}:${queryport}" message+=" Is my Game Server Online? -https://ismygameserver.online/${imgsoquerytype}/${alertip}:${queryport}" +${imgsourl}" fi if [ -n "${alerturl}" ]; then @@ -49,7 +52,21 @@ More info ${alerturl}" fi -json="$(jq -cn --arg body "${message}" '{msgtype: "m.notice", body: $body}')" +json="$(jq -cn \ + --arg body "${message}" \ + --arg title "${alerttitle}" \ + --arg servername "${servername}" \ + --arg information "${alertmessage}" \ + --arg game "${gamename}" \ + --arg serverip "${alertip}:${port}" \ + --arg servertime "${alerttime}" \ + --arg imgsourl "${imgsourl}" \ + --arg alerturl "${alerturl}" \ + '(@html "\($title)

Server Name
\($servername)

Information
\($information)

Game
\($game)

Server IP
\($serverip)

Server Time
\($servertime)") + + (if $imgsourl != "" then @html "

Is my Game Server Online?
Check here" else "" end) + + (if $alerturl != "" then @html "

More info
\($alerturl)" else "" end) + | gsub("'"; "'") + | {msgtype: "m.notice", body: $body, format: "org.matrix.custom.html", formatted_body: .}')" fn_print_dots "Sending Matrix alert" diff --git a/lgsm/modules/check.sh b/lgsm/modules/check.sh index 3922aec215..8e048a60ca 100755 --- a/lgsm/modules/check.sh +++ b/lgsm/modules/check.sh @@ -47,14 +47,14 @@ if [ "$(whoami)" != "root" ]; then done fi -allowed_commands_array=(BACKUP CONSOLE DEBUG DETAILS MAP-COMPRESSOR FASTDL MODS-INSTALL MODS-REMOVE MODS-UPDATE MONITOR POST-DETAILS RESTART START STOP TEST-ALERT CHANGE-PASSWORD UPDATE UPDATE-LGSM VALIDATE WIPE) +allowed_commands_array=(BACKUP CONSOLE DEBUG DETAILS MAP-COMPRESSOR FASTDL MODS-INSTALL MODS-REMOVE MODS-UPDATE MONITOR POST-DETAILS RESTART START STOP TEST-ALERT CHANGE-PASSWORD UPDATE UPDATE-LGSM VALIDATE WIPE WORKSHOP-UPDATE) for allowed_command in "${allowed_commands_array[@]}"; do if [ "${allowed_command}" == "${commandname}" ]; then check_logs.sh fi done -allowed_commands_array=(BACKUP DEBUG DETAILS RESTART START UPDATE) +allowed_commands_array=(BACKUP DEBUG DETAILS POST-DETAILS RESTART START UPDATE WORKSHOP-UPDATE) for allowed_command in "${allowed_commands_array[@]}"; do if [ "${allowed_command}" == "${commandname}" ]; then check_deps.sh @@ -77,7 +77,7 @@ for allowed_command in "${allowed_commands_array[@]}"; do fi done -allowed_commands_array=(DEBUG RESTART START UPDATE VALIDATE CHECK-UPDATE) +allowed_commands_array=(DEBUG RESTART START UPDATE VALIDATE CHECK-UPDATE WORKSHOP-UPDATE) for allowed_command in "${allowed_commands_array[@]}"; do if [ "${allowed_command}" == "${commandname}" ]; then if [ "${appid}" ]; then @@ -86,7 +86,7 @@ for allowed_command in "${allowed_commands_array[@]}"; do fi done -allowed_commands_array=(CHANGE-PASSWORD DETAILS MONITOR RESTART START STOP UPDATE VALIDATE POST-DETAILS) +allowed_commands_array=(CHANGE-PASSWORD DETAILS MONITOR RESTART START STOP UPDATE VALIDATE POST-DETAILS WORKSHOP-UPDATE) for allowed_command in "${allowed_commands_array[@]}"; do if [ "${allowed_command}" == "${commandname}" ]; then check_status.sh @@ -106,3 +106,13 @@ for allowed_command in "${allowed_commands_array[@]}"; do check_gamedig.sh fi done + +if [ "${shortname}" == "arma3" ] || [ "${shortname}" == "dayz" ] || [ "${shortname}" == "hw" ]; then + allowed_commands_array=(DEBUG DETAILS POST-DETAILS RESTART START) + for allowed_command in "${allowed_commands_array[@]}"; do + if [ "${allowed_command}" == "${commandname}" ] && { [ -n "${workshopmods}" ] || [ -f "${datadir}/${selfname}-workshop.txt" ]; }; then + workshop_core.sh + fn_workshop_mods_startparameters + fi + done +fi diff --git a/lgsm/modules/check_config.sh b/lgsm/modules/check_config.sh index 24bc1c37f5..05157e0169 100755 --- a/lgsm/modules/check_config.sh +++ b/lgsm/modules/check_config.sh @@ -7,6 +7,10 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" +if [ "${shortname}" == "orar" ] && [ ! -d "${servercfgdir}" ]; then + install_config.sh +fi + if [ -n "${servercfgfullpath}" ] && [ ! -f "${servercfgfullpath}" ]; then fn_print_warn_nl "Configuration file missing!" echo -e "${servercfgfullpath}" @@ -15,6 +19,14 @@ if [ -n "${servercfgfullpath}" ] && [ ! -f "${servercfgfullpath}" ]; then install_config.sh fi +if [ "${shortname}" == "ti" ] && [[ "${startparameters}" != *"DedicatedServerClientId"* ]] && [ ! -f "${servercfgdir}/Engine.ini" ]; then + fn_print_warn_nl "Configuration file missing!" + echo -e "${servercfgdir}/Engine.ini" + fn_script_log_warn "Configuration file missing!" + fn_script_log_warn "${servercfgdir}/Engine.ini" + install_config.sh +fi + if [ "${shortname}" == "rust" ] && [ -v rconpassword ] && [ -z "${rconpassword}" ]; then fn_print_fail_nl "RCON password is not set" fn_script_log_warn "RCON password is not set" @@ -37,3 +49,13 @@ elif [ "${shortname}" == "vh" ] && [ "${#serverpassword}" -le "4" ]; then fn_print_fail_nl "serverpassword is to short (min 5 chars)" fn_script_log_fail "serverpassword is to short (min 5 chars)" fi + +if [ "${shortname}" == "fivem" ] && ! grep -qE "^[[:space:]]*(set[[:space:]]+)?sv_licenseKey[[:space:]]+\"?[^\" ]" "${servercfgfullpath}" 2> /dev/null; then + fn_print_fail_nl "FiveM license key is not set" + echo -e "* Get a free key from ${italic}https://portal.cfx.re/servers/registration-keys${default}" + echo -e "* Set sv_licenseKey in ${servercfgfullpath}" + fn_script_log_fail "FiveM license key is not set" + if [ "${commandname}" == "START" ] || [ "${commandname}" == "DEBUG" ]; then + core_exit.sh + fi +fi diff --git a/lgsm/modules/check_deps.sh b/lgsm/modules/check_deps.sh index b031898970..3d5c4c8ec1 100755 --- a/lgsm/modules/check_deps.sh +++ b/lgsm/modules/check_deps.sh @@ -18,17 +18,19 @@ fn_install_dotnet_repo() { fi done - if [ "${distroid}" == "ubuntu" ]; then - # If the required .NET package is unavailable in Ubuntu repos, add the Microsoft repo. + if [ "${distroid}" == "ubuntu" ] || [ "${distroid}" == "debian" ]; then + # If the required .NET package is unavailable in Ubuntu/Debian repos, add the Microsoft repo. if ! apt-cache show "${dotnetpackage}" > /dev/null 2>&1; then - fn_fetch_file "https://packages.microsoft.com/config/ubuntu/${distroversion}/packages-microsoft-prod.deb" "" "" "" "/tmp" "packages-microsoft-prod.deb" "" "" "" "" - sudo dpkg -i /tmp/packages-microsoft-prod.deb - fi - elif [ "${distroid}" == "debian" ]; then - # If the required .NET package is unavailable in Debian repos, add the Microsoft repo. - if ! apt-cache show "${dotnetpackage}" > /dev/null 2>&1; then - fn_fetch_file "https://packages.microsoft.com/config/debian/${distroversion}/packages-microsoft-prod.deb" "" "" "" "/tmp" "packages-microsoft-prod.deb" "" "" "" "" - sudo dpkg -i /tmp/packages-microsoft-prod.deb + if [ "${autodepinstall}" == "0" ]; then + fn_fetch_file "https://packages.microsoft.com/config/${distroid}/${distroversion}/packages-microsoft-prod.deb" "" "" "" "/tmp" "packages-microsoft-prod.deb" "" "" "" "" + sudo dpkg -i /tmp/packages-microsoft-prod.deb + else + fn_print_information_nl "Installing Microsoft repository." + fn_print_warning_nl "${nosudomessage}" + echo -e "Follow instructions on Microsoft website to install." + echo -e "https://learn.microsoft.com/en-us/dotnet/core/install/linux" + fn_script_log_warn "Unable to install Microsoft repository. ${nosudomessage}" + fi fi fi } @@ -37,13 +39,15 @@ fn_install_mono_repo() { if [ "${autodepinstall}" == "0" ]; then fn_print_information_nl "Automatically adding Mono repository." fn_script_log_info "Automatically adding Mono repository." - echo -en ".\r" - fn_sleep_time_1 - echo -en "..\r" - fn_sleep_time_1 - echo -en "...\r" - fn_sleep_time_1 - echo -en " \r" + if [ -z "${plainoutput}" ]; then + echo -en ".\r" + fn_sleep_time_1 + echo -en "..\r" + fn_sleep_time_1 + echo -en "...\r" + fn_sleep_time_1 + echo -en " \r" + fi if [ "${distroid}" == "ubuntu" ]; then if [ "${distroversion}" == "22.04" ]; then cmd="sudo apt-get install gnupg ca-certificates;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/ubuntu stable-jammy main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update" @@ -111,10 +115,10 @@ fn_install_mono_repo() { else fn_print_information_nl "Installing Mono repository." - fn_print_warning_nl "$(whoami) does not have sudo access." + fn_print_warning_nl "${nosudomessage}" echo -e "Follow instructions on Mono website to install." echo -e "https://www.mono-project.com/download/stable/#download-lin" - fn_script_log_warn "Unable to install Mono repository. $(whoami) does not have sudo access." + fn_script_log_warn "Unable to install Mono repository. ${nosudomessage}" fi } @@ -156,13 +160,19 @@ fn_install_missing_deps() { fn_script_log_warn "Missing dependencies: ${array_deps_missing[*]}" fi - # Attempt automatic dependency installation - if [ "${autoinstall}" == "1" ]; then - sudo -n true > /dev/null 2>&1 + # Attempt automatic dependency installation. + # Check for passwordless sudo first: sudo-rs (default sudo from Ubuntu 25.10) always asks + # for a password for sudo -v, even when the user has NOPASSWD. + if sudo -n true > /dev/null 2>&1; then + autodepinstall="0" + elif [ "${autoinstall}" == "1" ]; then + autodepinstall="1" + nosudomessage="sudo cannot run without a password during auto-install." else sudo -v > /dev/null 2>&1 + autodepinstall="$?" + nosudomessage="$(whoami) does not have sudo access." fi - autodepinstall="$?" if [ "${monoinstalled}" == "false" ]; then fn_install_mono_repo @@ -177,8 +187,8 @@ fn_install_missing_deps() { fn_print_information_nl "$(whoami) has sudo access." fn_script_log_info "$(whoami) has sudo access." else - fn_print_warning_nl "$(whoami) does not have sudo access. Manually install dependencies or run ./${selfname} install as root." - fn_script_log_warn "$(whoami) does not have sudo access. Manually install dependencies or run ./${selfname} install as root." + fn_print_warning_nl "${nosudomessage} Manually install dependencies or run ./${selfname} install as root." + fn_script_log_warn "${nosudomessage} Manually install dependencies or run ./${selfname} install as root." fi fi @@ -193,13 +203,15 @@ fn_install_missing_deps() { if [ "${autodepinstall}" == "0" ]; then fn_print_information_nl "Automatically installing missing dependencies." fn_script_log_info "Automatically installing missing dependencies." - echo -en ".\r" - fn_sleep_time_1 - echo -en "..\r" - fn_sleep_time_1 - echo -en "...\r" - fn_sleep_time_1 - echo -en " \r" + if [ -z "${plainoutput}" ]; then + echo -en ".\r" + fn_sleep_time_1 + echo -en "..\r" + fn_sleep_time_1 + echo -en "...\r" + fn_sleep_time_1 + echo -en " \r" + fi if [ "$(command -v apt 2> /dev/null)" ]; then cmd="echo steamcmd steam/question select \"I AGREE\" | sudo debconf-set-selections; echo steamcmd steam/license note '' | sudo debconf-set-selections; ${i386installcommand}sudo apt-get update; sudo apt-get -y install ${array_deps_missing[*]}" eval "${cmd}" @@ -256,10 +268,16 @@ fn_check_loop() { done # user will be informed of any missing dependencies. - fn_install_missing_deps + if [ "${depcheckonly}" != "1" ]; then + fn_install_missing_deps + fi } # Checks if dependency is installed or not. +fn_deps_version_ge() { + [ "$(printf '%s\n' "$1" "$2" | sort -V | head -1)" == "$2" ] +} + fn_deps_detector() { ## Check. # SteamCMD: Will be removed from required array if no appid is present or non-free repo is not available. @@ -272,7 +290,8 @@ fn_deps_detector() { array_deps_required=("${array_deps_required[@]/steamcmd/}") steamcmdstatus=1 return - elif [ "${deptocheck}" == "steamcmd" ] && [ "${distroid}" == "debian" ] && ! grep -qE '[^deb]+non-free([^-]|$)' /etc/apt/sources.list; then + # Checks classic and deb822 sources for an uncommented non-free component (non-free-firmware does not count). + elif [ "${deptocheck}" == "steamcmd" ] && [ "${distroid}" == "debian" ] && ! grep -qE '^[[:space:]]*[^#[:space:]].*[[:space:]]non-free([[:space:]]|$)' /etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources 2> /dev/null; then array_deps_required=("${array_deps_required[@]/steamcmd/}") steamcmdstatus=1 return @@ -280,11 +299,75 @@ fn_deps_detector() { elif [[ ${deptocheck} == "openjdk"* ]] || [[ ${deptocheck} == "java"* ]]; then # Is java already installed? if [ -n "${javaversion}" ]; then - # Added for users using Oracle JRE to bypass check. - depstatus=0 - deptocheck="${javaversion}" + javamajorversion="$(echo "${javaversion}" | grep -Eo 'version "[0-9]+' | grep -Eo '[0-9]+' | head -1)" + javarequiredmajor="$(echo "${deptocheck}" | grep -Eo '[0-9]+' | head -1)" + if [ "${shortname}" == "mc" ] || [ "${shortname}" == "pmc" ]; then + if [ "${mcversion}" == "latest" ]; then + javarequiredmajor="25" + elif [[ "${mcversion}" =~ ^[0-9]+\.[0-9]+([.][0-9]+)?$ ]]; then + if fn_deps_version_ge "${mcversion}" "26.1"; then + javarequiredmajor="25" + elif [ "${shortname}" == "mc" ] && fn_deps_version_ge "${mcversion}" "1.20.5"; then + javarequiredmajor="21" + elif [ "${shortname}" == "pmc" ] && fn_deps_version_ge "${mcversion}" "1.20" && fn_deps_version_ge "1.21.11" "${mcversion}"; then + javarequiredmajor="21" + elif [ "${shortname}" == "pmc" ] && fn_deps_version_ge "${mcversion}" "1.17" && fn_deps_version_ge "1.19" "${mcversion}"; then + javarequiredmajor="17" + elif [ "${shortname}" == "pmc" ] && [ "${mcversion}" == "1.16.5" ]; then + javarequiredmajor="16" + elif [ "${shortname}" == "pmc" ] && fn_deps_version_ge "${mcversion}" "1.12" && ! fn_deps_version_ge "${mcversion}" "1.16.5"; then + javarequiredmajor="11" + elif [ "${shortname}" == "pmc" ] && ! fn_deps_version_ge "${mcversion}" "1.16.5"; then + javarequiredmajor="8" + fi + fi + fi + if [ "${shortname}" == "hyt" ] && { [ -z "${javamajorversion}" ] || [ "${javamajorversion}" -lt "25" ]; }; then + # Java 25 installed but not the active java: installing it again would not change that. + if compgen -G "/usr/lib/jvm/*25*/bin/java" > /dev/null; then + depstatus=0 + deptocheck="${javaversion}" + fn_print_warn_nl "Java 25 is installed but the active java is version ${javamajorversion:-unknown}. Select Java 25 with: sudo update-alternatives --config java" + fn_script_log_warn "Java 25 is installed but the active java is version ${javamajorversion:-unknown}" + else + depstatus=1 + fi + elif [ -n "${javamajorversion}" ] && [ "${javamajorversion}" -lt "${javarequiredmajor}" ]; then + if [ "${depcheckonly}" == "1" ]; then + depstatus=1 + elif [ "${javarequiredmajor}" -gt "$(echo "${deptocheck}" | grep -Eo '[0-9]+' | head -1)" ]; then + fn_print_failure_nl "${gamename} ${mcversion} requires Java ${javarequiredmajor}; ${distroname} does not provide that version as a package." + echo -e "Install Java ${javarequiredmajor} manually or upgrade to Debian 13 or Ubuntu 24.04+." + fn_script_log_fail "${gamename} ${mcversion} requires Java ${javarequiredmajor}; ${distroname} does not provide it as a package." + core_exit.sh + else + fn_print_failure_nl "${gamename} ${mcversion} requires Java ${javarequiredmajor}; active Java is ${javamajorversion}." + echo -e "Select a compatible Java runtime with: sudo update-alternatives --config java" + fn_script_log_fail "${gamename} ${mcversion} requires Java ${javarequiredmajor}; active Java is ${javamajorversion}." + core_exit.sh + fi + else + # Added for users using Oracle JRE to bypass check. + depstatus=0 + deptocheck="${javaversion}" + fi else - depstatus=1 + javarequiredmajor="$(echo "${deptocheck}" | grep -Eo '[0-9]+' | head -1)" + if [ "${shortname}" == "mc" ] || [ "${shortname}" == "pmc" ]; then + if [ "${mcversion}" == "latest" ] || fn_deps_version_ge "${mcversion}" "26.1"; then + javarequiredmajor="25" + elif { [ "${shortname}" == "mc" ] && fn_deps_version_ge "${mcversion}" "1.20.5"; } || { [ "${shortname}" == "pmc" ] && fn_deps_version_ge "${mcversion}" "1.20" && fn_deps_version_ge "1.21.11" "${mcversion}"; }; then + javarequiredmajor="21" + fi + fi + if [ "${javarequiredmajor}" -gt "$(echo "${deptocheck}" | grep -Eo '[0-9]+' | head -1)" ] && [ "${depcheckonly}" != "1" ]; then + fn_print_failure_nl "${gamename} ${mcversion} requires Java ${javarequiredmajor}; ${distroname} does not provide that version as a package." + echo -e "Install Java ${javarequiredmajor} manually or upgrade to Debian 13 or Ubuntu 24.04+." + fn_script_log_fail "${gamename} ${mcversion} requires Java ${javarequiredmajor}; ${distroname} does not provide it as a package." + core_exit.sh + else + depstatus=1 + fi fi # Mono: A Mono repo needs to be installed. elif [ "${deptocheck}" == "mono-complete" ]; then @@ -353,6 +436,10 @@ fn_deps_detector() { fi } +if [ "${commandname}" == "DETAILS" ] || [ "${commandname}" == "POST-DETAILS" ]; then + depcheckonly="1" +fi + if [ "${commandname}" == "INSTALL" ]; then if [ "$(whoami)" == "root" ]; then echo -e "" @@ -369,38 +456,42 @@ fi info_distro.sh -# Will warn user if their distro is no longer supported by the vendor. -if [ -n "${distrosupport}" ]; then - if [ "${distrosupport}" == "unsupported" ]; then - fn_print_warning_nl "${distroname} is no longer supported by the vendor or LinuxGSM. Upgrading is recommended." - fn_script_log_warn "${distroname} is no longer supported by the vendor or LinuxGSM. Upgrading is recommended." +if [ "${depcheckonly}" != "1" ]; then + # Will warn user if their distro is no longer supported by the vendor. + if [ -n "${distrosupport}" ]; then + if [ "${distrosupport}" == "unsupported" ]; then + fn_print_warning_nl "${distroname} is no longer supported by the vendor or LinuxGSM. Upgrading is recommended." + fn_script_log_warn "${distroname} is no longer supported by the vendor or LinuxGSM. Upgrading is recommended." + fi fi -fi -# These titles are only supported up to Ubuntu 22.04 (Jammy) and Debian 12 (Bookworm). -if { [ "${distroid}" == "ubuntu" ] && dpkg --compare-versions "${distroversion}" "gt" "22.04"; } || { [ "${distroid}" == "debian" ] && dpkg --compare-versions "${distroversion}" "gt" "12"; }; then - if [ "${shortname}" == "bf1942" ] || [ "${shortname}" == "bfv" ]; then - fn_print_failure_nl "${gamename} is not supported on ${distroname} (requires Ubuntu <= 22.04 or Debian <= 12)." - fn_script_log_fail "${gamename} is not supported on ${distroname}." - core_exit.sh + # These titles are only supported up to Ubuntu 20.04 and Debian 11. + if { [ "${distroid}" == "ubuntu" ] && dpkg --compare-versions "${distroversion}" "gt" "20.04"; } || { [ "${distroid}" == "debian" ] && dpkg --compare-versions "${distroversion}" "gt" "11"; }; then + if [ "${shortname}" == "onset" ] || [ "${shortname}" == "btl" ]; then + fn_print_failure_nl "${gamename} is not supported on ${distroname} (requires Ubuntu <= 20.04 or Debian <= 11)." + fn_script_log_fail "${gamename} is not supported on ${distroname}." + core_exit.sh + fi fi -fi -# These titles are only supported up to Ubuntu 20.04 and Debian 11. -if { [ "${distroid}" == "ubuntu" ] && dpkg --compare-versions "${distroversion}" "gt" "20.04"; } || { [ "${distroid}" == "debian" ] && dpkg --compare-versions "${distroversion}" "gt" "11"; }; then - if [ "${shortname}" == "onset" ] || [ "${shortname}" == "btl" ]; then - fn_print_failure_nl "${gamename} is not supported on ${distroname} (requires Ubuntu <= 20.04 or Debian <= 11)." - fn_script_log_fail "${gamename} is not supported on ${distroname}." - core_exit.sh + # Vintage Story tracks newer .NET runtimes; older distro releases may not ship required packages. + if [ "${shortname}" == "vints" ]; then + if { [ "${distroid}" == "ubuntu" ] && dpkg --compare-versions "${distroversion}" "lt" "24.04"; } || { [ "${distroid}" == "debian" ] && dpkg --compare-versions "${distroversion}" "lt" "12"; } || [ "${distroid}" == "centos" ] || [ "${distroid}" == "rhel" ] || [ "${distroid}" == "rocky" ] || [ "${distroid}" == "almalinux" ]; then + fn_print_warning_nl "${gamename} may require newer .NET runtimes than ${distroname} provides." + echo -e "If startup fails due to missing .NET runtime, upgrading to Ubuntu 24.04+ or Debian 12+ is recommended." + fn_script_log_warn "${gamename} may require newer .NET runtimes than ${distroname} provides." + fi fi -fi -# Vintage Story tracks newer .NET runtimes; older distro releases may not ship required packages. -if [ "${shortname}" == "vints" ]; then - if { [ "${distroid}" == "ubuntu" ] && dpkg --compare-versions "${distroversion}" "lt" "24.04"; } || { [ "${distroid}" == "debian" ] && dpkg --compare-versions "${distroversion}" "lt" "12"; } || [ "${distroid}" == "centos" ] || [ "${distroid}" == "rhel" ] || [ "${distroid}" == "rocky" ] || [ "${distroid}" == "almalinux" ]; then - fn_print_warning_nl "${gamename} may require newer .NET runtimes than ${distroname} provides." - echo -e "If startup fails due to missing .NET runtime, upgrading to Ubuntu 24.04+ or Debian 12+ is recommended." - fn_script_log_warn "${gamename} may require newer .NET runtimes than ${distroname} provides." + # Hytale needs Java 25, which Ubuntu before 22.04, Debian before 13 and RHEL before 9 do not package. + if [ "${shortname}" == "hyt" ]; then + if { [ "${distroid}" == "ubuntu" ] && [ "${distroversion}" != "22.04" ] && dpkg --compare-versions "${distroversion}" "lt" "24.04"; } || { [ "${distroid}" == "debian" ] && dpkg --compare-versions "${distroversion}" "lt" "13"; } || { [ -n "${distroversionrh}" ] && [ "${distroversionrh}" -lt "9" ]; }; then + if ! echo "${javaversion}" | grep -Eq 'version "(2[5-9]|[3-9][0-9])'; then + fn_print_warning_nl "${gamename} requires Java 25, which ${distroname} does not provide." + echo -e "Install Java 25 manually or upgrade to Ubuntu 22.04+, Debian 13+ or a RHEL 9 based distro." + fn_script_log_warn "${gamename} requires Java 25, which ${distroname} does not provide." + fi + fi fi fi @@ -424,10 +515,16 @@ if [ -f "${datadir}/${distroid}-${distroversioncsv}.csv" ]; then array_deps_required=("${depall} ${depsteamcmd} ${depshortname}") array_deps_required_steamcmd=("${depsteamcmd}") fn_deps_email + if [ "${logtimestamp}" == "on" ]; then + array_deps_required+=(gawk) + fi # Unique sort dependency array. IFS=" " read -r -a array_deps_required <<< "$(echo "${array_deps_required[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')" fn_check_loop +elif [ "${depcheckonly}" == "1" ]; then + # shellcheck disable=SC2034 # Used by info_messages.sh. + depcheckunavailable="1" # Warn the user that dependency checking is unavailable for their distro. elif [ "${commandname}" == "INSTALL" ] || [ -n "${checkflag}" ] && [ "${checkflag}" != "0" ]; then fn_print_warning_nl "LinuxGSM dependency checking currently unavailable for ${distroname}." diff --git a/lgsm/modules/check_gamedig.sh b/lgsm/modules/check_gamedig.sh index 72d3700fec..630834e874 100755 --- a/lgsm/modules/check_gamedig.sh +++ b/lgsm/modules/check_gamedig.sh @@ -13,11 +13,11 @@ if [ "$(command -v node)" ] && [ "$(command -v npm)" ] && [ "$(node -v | cut -d fn_script_log_info "Installing Gamedig" cd "${lgsmdir}" || exit curl -L -o package.json "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/package.json" - npm install + npm install --no-audit elif [ "$(command -v node)" ] && [ "$(command -v npm)" ] && [ "$(node -v | cut -d 'v' -f 2 | cut -d '.' -f 1)" -ge 16 ]; then cd "${lgsmdir}" || exit curl -s -L -o package.json "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/package.json" - npm update > /dev/null 2>&1 + npm update --no-audit --fetch-timeout=10000 --fetch-retries=0 > /dev/null 2>&1 else fn_script_log_info "Install Node.js and NPM to enable Gamedig" fi diff --git a/lgsm/modules/check_ip.sh b/lgsm/modules/check_ip.sh index 8f943c5687..57c7f5e8f2 100755 --- a/lgsm/modules/check_ip.sh +++ b/lgsm/modules/check_ip.sh @@ -61,3 +61,9 @@ else httpip=("${ip}") telnetip=("${ip}") fi + +# If the game config binds its query interface to a specific IPv4 address (e.g. TeamSpeak 3 query_ip), +# query that address first. This also covers a query interface bound to localhost. +if grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' <<< "${configqueryip}" && [ "${configqueryip}" != "0.0.0.0" ] && [[ " ${queryips[*]} " != *" ${configqueryip} "* ]]; then + queryips=("${configqueryip}" "${queryips[@]}") +fi diff --git a/lgsm/modules/check_permissions.sh b/lgsm/modules/check_permissions.sh index 3dc521da7a..75eb45bb83 100755 --- a/lgsm/modules/check_permissions.sh +++ b/lgsm/modules/check_permissions.sh @@ -7,44 +7,31 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" +# Lists files the current user neither owns nor can access. +fn_find_ownership_issues() { + find "$@" -not -user "$(whoami)" \( -not -readable -o -not -writable -o \( -type d -not -executable \) \) -printf "%u\t%g\t%M\t%p\n" +} + fn_check_ownership() { - if [ -f "${rootdir}/${selfname}" ]; then - if [ "$(find "${rootdir}/${selfname}" -not -user "$(whoami)" | wc -l)" -ne "0" ]; then - selfownissue=1 - fi - fi - if [ -d "${lgsmdir}" ]; then - if [ "$(find "${lgsmdir}" -not -user "$(whoami)" | wc -l)" -ne "0" ]; then - lgsmownissue=1 + ownershipissues="$( + if [ -f "${rootdir}/${selfname}" ]; then + fn_find_ownership_issues "${rootdir}/${selfname}" fi - fi - if [ -d "${modulesdir}" ]; then - if [ "$(find "${modulesdir}" -not -name '*.swp' -not -user "$(whoami)" | wc -l)" -ne "0" ]; then - funcownissue=1 + if [ -d "${lgsmdir}" ]; then + fn_find_ownership_issues "${lgsmdir}" -not -name '*.swp' fi - fi - if [ -d "${serverfiles}" ]; then - if [ "$(find "${serverfiles}" -not -path "*/steamapps/compatdata/*" -not -name '*.swp' -not -user "$(whoami)" | wc -l)" -ne "0" ]; then - filesownissue=1 + if [ -d "${serverfiles}" ]; then + fn_find_ownership_issues "${serverfiles}" -not -path "*/steamapps/compatdata/*" -not -name '*.swp' fi - fi - if [ "${selfownissue}" == "1" ] || [ "${lgsmownissue}" == "1" ] || [ "${filesownissue}" == "1" ]; then + )" + if [ -n "${ownershipissues}" ]; then fn_print_fail_nl "Ownership issues found" fn_script_log_fail "Ownership issues found" - fn_print_information_nl "The current user ($(whoami)) does not have ownership of the following files:" - fn_script_log_info "The current user ($(whoami)) does not have ownership of the following files:" + fn_print_information_nl "The current user ($(whoami)) does not own and cannot access the following files:" + fn_script_log_info "The current user ($(whoami)) does not own and cannot access the following files:" { - echo -en "User\tGroup\tFile:" - if [ "${selfownissue}" == "1" ]; then - find "${rootdir}/${selfname}" -not -user "$(whoami)" -printf "%u\t%g\t%p\n" - fi - if [ "${lgsmownissue}" == "1" ]; then - find "${lgsmdir}" -not -user "$(whoami)" -printf "%u\t%g\t%p\n" - fi - if [ "${filesownissue}" == "1" ]; then - find "${serverfiles}" -not -path "*/steamapps/compatdata/*" -not -user "$(whoami)" -printf "%u\t%g\t%p\n" - fi - + echo -e "User\tGroup\tMode\tFile" + echo "${ownershipissues}" } | column -s $'\t' -t | tee -a "${lgsmlog}" echo -e "" fn_print_information_nl "please see https://docs.linuxgsm.com/support/faq#fail-starting-game-server-permission-issues-found" @@ -102,7 +89,7 @@ fn_check_permissions() { # Grab the first and second digit for user and group permission. userrootdirperm="${rootdirperm:0:1}" grouprootdirperm="${rootdirperm:1:1}" - if [ "${userrootdirperm}" != "7" ] && [ "${grouprootdirperm}" != "7" ]; then + if [ "${userrootdirperm}" != "7" ] && [ "${grouprootdirperm}" != "7" ] && { [ ! -r "${rootdir}" ] || [ ! -w "${rootdir}" ] || [ ! -x "${rootdir}" ]; }; then fn_print_fail_nl "Permissions issues found" fn_script_log_fail "Permissions issues found" fn_print_information_nl "The following directory does not have the correct permissions:" @@ -120,7 +107,7 @@ fn_check_permissions() { # Check if executable is executable and attempt to fix it. # First get executable name. execname=$(basename "${executable}") - if [ -f "${executabledir}/${execname}" ]; then + if [ -f "${executabledir}/${execname}" ] && [ ! -x "${executabledir}/${execname}" ]; then # Get permission numbers on file under the form 775. execperm=$(stat -c %a "${executabledir}/${execname}") # Grab the first and second digit for user and group permission. diff --git a/lgsm/modules/check_players_online.sh b/lgsm/modules/check_players_online.sh index b38de1f704..4034d35f01 100755 --- a/lgsm/modules/check_players_online.sh +++ b/lgsm/modules/check_players_online.sh @@ -3,32 +3,39 @@ # Author: Daniel Gibbs # Contributors: https://linuxgsm.com/contrib # Website: https://linuxgsm.com -# Description: Queries the server with gamedig and sets ${playersonline} to the -# current player count when players are connected (empty otherwise). -# Used by the stoponlyifnoplayers feature to postpone stop/restart. +# Description: Checks if players are on the server. moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" playersonline="" -if [ "${stoponlyifnoplayers}" == "on" ]; then - if [ "${querymode}" == "2" ] || [ "${querymode}" == "3" ]; then - querysucceeded="0" +playerscounted="" +playercountunavailable="" +if [ "${stoponlyifnoplayers}" == "on" ] || [ "${playercheckforce}" == "1" ]; then + if [ "${querymode}" != "2" ] && [ "${querymode}" != "3" ]; then + playercountunavailable="querymode ${querymode} cannot count players" + elif [ ! -f "${lgsmdir}/node_modules/gamedig/bin/gamedig.js" ] && [ ! "$(command -v gamedig 2> /dev/null)" ]; then + playercountunavailable="gamedig is not installed" + elif [ ! "$(command -v jq 2> /dev/null)" ]; then + playercountunavailable="jq is not installed" + else for queryip in "${queryips[@]}"; do query_gamedig.sh if [ "${querystatus}" == "0" ]; then - querysucceeded="1" + playerscounted="1" if [ -n "${gdplayers}" ] && [ "${gdplayers}" -ne 0 ]; then playersonline="${gdplayers}" break fi fi done - # The query failed for every configured IP, so the player count could not be - # determined. Fail open (proceed as if empty) rather than block the server - # indefinitely, but warn clearly since the safety check did not actually run. - if [ "${querysucceeded}" == "0" ]; then - fn_print_warn_nl "Unable to determine player count: stoponlyifnoplayers check skipped" - fn_script_log_warn "Unable to determine player count via gamedig: stoponlyifnoplayers check skipped" + if [ "${playerscounted}" != "1" ]; then + playercountunavailable="query failed" fi fi + # The player count could not be determined. Fail open (proceed as if empty) rather than + # block the server indefinitely, but warn clearly since the check did not actually run. + if [ -n "${playercountunavailable}" ] && [ "${playercheckforce}" != "1" ]; then + fn_print_warn_nl "Unable to determine player count (${playercountunavailable}): stoponlyifnoplayers check skipped" + fn_script_log_warn "Unable to determine player count (${playercountunavailable}): stoponlyifnoplayers check skipped" + fi fi diff --git a/lgsm/modules/check_system_requirements.sh b/lgsm/modules/check_system_requirements.sh index f34190fecf..eb97b00a4a 100755 --- a/lgsm/modules/check_system_requirements.sh +++ b/lgsm/modules/check_system_requirements.sh @@ -25,12 +25,16 @@ elif [ "${shortname}" == "bt" ]; then ramrequirementgb="1" elif [ "${shortname}" == "cc" ]; then ramrequirementgb="1" +elif [ "${shortname}" == "ce" ]; then + ramrequirementgb="8" elif [ "${shortname}" == "dayz" ]; then ramrequirementgb="5" elif [ "${shortname}" == "dodr" ]; then ramrequirementgb="2" elif [ "${shortname}" == "hw" ]; then ramrequirementgb="3" +elif [ "${shortname}" == "hyt" ]; then + ramrequirementgb="4" elif [ "${shortname}" == "mc" ]; then ramrequirementgb="1" elif [ "${shortname}" == "pmc" ]; then @@ -45,6 +49,12 @@ elif [ "${shortname}" == "pvr" ]; then ramrequirementgb="1" elif [ "${shortname}" == "pz" ]; then ramrequirementgb="3" +elif [ "${shortname}" == "rsdw" ]; then + ramrequirementgb="2" +elif [ "${shortname}" == "bfe" ]; then + ramrequirementgb="2" +elif [ "${shortname}" == "rwr" ]; then + ramrequirementgb="1" elif [ "${shortname}" == "rust" ]; then ramrequirementgb="9" elif [ "${shortname}" == "sdtd" ]; then diff --git a/lgsm/modules/check_update_lock.sh b/lgsm/modules/check_update_lock.sh new file mode 100755 index 0000000000..42e64e9e39 --- /dev/null +++ b/lgsm/modules/check_update_lock.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# LinuxGSM check_update_lock.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Stops an update or validate from running while another one is running. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +updatinglock="${lockdir}/updating.lock" + +fn_update_lock_create() { + ( + set -o noclobber + echo "$$" > "${updatinglock}" + ) 2> /dev/null +} + +# Checks the PID in the lockfile is running and started before the lockfile was written. +fn_update_lock_running() { + local lockpid="${1}" + local lockage processage + if [ -z "${lockpid}" ] || ! kill -0 "${lockpid}" 2> /dev/null; then + return 1 + fi + lockage="$(($(date '+%s') - $(stat -c %Y "${updatinglock}" 2> /dev/null || echo 0)))" + processage="$(ps -o etimes= -p "${lockpid}" 2> /dev/null | tr -d ' ')" + [ -n "${processage}" ] && [ "$((processage + 2))" -ge "${lockage}" ] +} + +if ! fn_update_lock_create; then + updatelockpid="$(cat "${updatinglock}" 2> /dev/null)" + if [ -z "${updatelockpid}" ]; then + sleep 1 + updatelockpid="$(cat "${updatinglock}" 2> /dev/null)" + fi + if [ "${updatelockpid}" == "$$" ] && [ -n "${updatelocklevel}" ]; then + return + fi + if [ "${updatelockpid}" == "$$" ] || ! fn_update_lock_running "${updatelockpid}"; then + fn_script_log_warn "Checking update: Removing stale lockfile from PID ${updatelockpid:-unknown}" + rm -f "${updatinglock:?}" + fn_update_lock_create + fi +fi + +updatelockpid="$(cat "${updatinglock}" 2> /dev/null)" +if [ "${updatelockpid}" != "$$" ]; then + fn_print_dots "Checking update" + fn_print_checking_eol + fn_print_info "Checking update: Update is already running (PID ${updatelockpid})" + fn_print_info_eol_nl + fn_script_log_info "Checking update: Update is already running (PID ${updatelockpid})" + # shellcheck disable=SC2034 # Used by core_exit.sh. + exitcode=0 + unset exitbypass + core_exit.sh +fi +updatelocklevel="${BASH_SUBSHELL}" diff --git a/lgsm/modules/command_backup.sh b/lgsm/modules/command_backup.sh index 5892a81eb2..28dedb6984 100755 --- a/lgsm/modules/command_backup.sh +++ b/lgsm/modules/command_backup.sh @@ -12,6 +12,9 @@ fn_firstcommand_set # Trap to remove lockfile on quit. fn_backup_trap() { + if [ "$(type -t fn_stop_warn_players_cancel)" == "function" ]; then + fn_stop_warn_players_cancel + fi echo -e "" echo -en "backup ${backupname}.${compressext}..." fn_print_canceled_eol_nl @@ -29,8 +32,10 @@ fn_backup_trap() { # Check if a backup is pending or has been aborted using backup.lock. fn_backup_check_lockfile() { - # Remove stale lockfile. - if [ -f "${lockdir}/backup.lock" ]; then + # Remove stale lockfile, unless a long backup is still running. + local backupsrunning + backupsrunning="$(pgrep -fc -u "$(id -u)" "^([^ ]*/)?bash ([^ ]*/)?${selfname} (backup|b)( |$)")" + if [ -f "${lockdir}/backup.lock" ] && [ "${backupsrunning:-0}" -le 1 ]; then if [ "$(find "${lockdir}/backup.lock" -mmin +60)" ]; then fn_print_dots "Lockfile found: " fn_print_checking_eol @@ -130,8 +135,52 @@ fn_select_compression() { fi } +# Game data kept outside rootdir, such as worlds saved under the home directory. +fn_backup_extradirs() { + local candidates=() + local covered=() dir dirreal link coveredpath + backupextradirs=() + if [ "${shortname}" == "bt" ]; then + candidates+=("${XDG_DATA_HOME:-${HOME}/.local/share}/Daedalic Entertainment GmbH/Barotrauma") + elif [ "${shortname}" == "ct" ]; then + candidates+=("${serverfiles}DedicatedServerSave") + elif [ "${shortname}" == "dst" ]; then + candidates+=("${persistentstorageroot}") + elif [ "${shortname}" == "pz" ]; then + candidates+=("${HOME}/Zomboid") + elif [ "${shortname}" == "scpsl" ]; then + candidates+=("${HOME}/.config/SCP Secret Laboratory/config") + elif [ "${shortname}" == "sdtd" ]; then + candidates+=("${HOME}/.local/share/7DaysToDie/Saves") + fi + candidates+=("${savedir}" "${servercfgdir}") + covered+=("$(readlink -f "${rootdir}")") + while IFS= read -r link; do + covered+=("$(readlink -f "${link}")") + done < <(find "${rootdir}" -maxdepth 2 -type l 2> /dev/null) + for dir in "${candidates[@]}"; do + if [ -z "${dir}" ] || [ ! -d "${dir}" ]; then + continue + fi + dirreal="$(readlink -f "${dir}")" + for coveredpath in "${covered[@]}" "${backupextradirs[@]}"; do + if [[ "${dirreal}/" == "${coveredpath}/"* ]]; then + continue 2 + fi + done + backupextradirs+=("${dirreal}") + done +} + # Compressing files. fn_backup_compression() { + fn_backup_extradirs + backupextras=() + for extradir in "${backupextradirs[@]}"; do + echo -e "* Including ${extradir}" + fn_script_log_info "Including ${extradir}" + backupextras+=(-C / "${extradir#/}") + done fn_print_info "A total of ${rootdirduexbackup} will be compressed." fn_script_log_info "A total of ${rootdirduexbackup} will be compressed: ${backupdir}/${backupname}.${compressext}" @@ -139,16 +188,21 @@ fn_backup_compression() { fn_script_log_info "Backup ${rootdirduexbackup} ${backupname}.${compressext}, in progress" excludedir=$(fn_backup_relpath) - if [ ! -d "${excludedir}" ]; then + if [ ! -d "${rootdir}/${excludedir}" ]; then fn_print_fail_nl "Problem identifying the previous backup directory for exclusion." fn_script_log_fail "Problem identifying the previous backup directory for exclusion" core_exit.sh fi + backupexcludes=(--exclude "${excludedir}" --exclude "${lockdir}" --exclude "${tmpdir}") + if [[ "${backupdir}" == "${rootdir}/"* ]]; then + backupexcludes+=(--exclude "./${backupdir#"${rootdir}"/}") + fi + if [ -n "${compressflag}" ]; then - tar ${compressflag} -hcf "${backupdir}/${backupname}.${compressext}" -C "${rootdir}" --exclude "${excludedir}" --exclude "${lockdir}" --exclude "${tmpdir}" ./. + tar ${compressflag} -hcf "${backupdir}/${backupname}.${compressext}" "${backupexcludes[@]}" -C "${rootdir}" ./. "${backupextras[@]}" else - tar -hcf "${backupdir}/${backupname}.${compressext}" -C "${rootdir}" --exclude "${excludedir}" --exclude "${lockdir}" --exclude "${tmpdir}" ./. + tar -hcf "${backupdir}/${backupname}.${compressext}" "${backupexcludes[@]}" -C "${rootdir}" ./. "${backupextras[@]}" fi exitcode=$? @@ -164,6 +218,8 @@ fn_backup_compression() { fn_script_log_pass "Backup created: ${backupname}.${compressext}, total size $(du -sh "${backupdir}/${backupname}.${compressext}" | awk '{print $1}')" alert="backup" alert.sh + # A postponed backup is complete. + rm -f "${lockdir:?}/${selfname}-backup-request.lock" fi } diff --git a/lgsm/modules/command_check_update.sh b/lgsm/modules/command_check_update.sh index 93a770e794..78c04242ca 100755 --- a/lgsm/modules/command_check_update.sh +++ b/lgsm/modules/command_check_update.sh @@ -24,22 +24,41 @@ elif [ "${shortname}" == "pmc" ] || [ "${shortname}" == "vpmc" ] || [ "${shortna update_pmc.sh elif [ "${shortname}" == "fctr" ]; then update_fctr.sh +elif [ "${shortname}" == "fivem" ]; then + update_fivem.sh +elif [ "${shortname}" == "hyt" ]; then + update_hyt.sh elif [ "${shortname}" == "mta" ]; then update_mta.sh elif [ "${shortname}" == "jk2" ]; then update_jk2.sh +elif [ "${shortname}" == "jk3" ]; then + update_jk3.sh +elif [ "${shortname}" == "luanti" ]; then + update_luanti.sh +elif [ "${shortname}" == "orar" ]; then + update_openra.sh elif [ "${shortname}" == "vints" ]; then update_vints.sh +elif [ "${shortname}" == "bfe" ]; then + update_bfe.sh elif [ "${shortname}" == "bb" ]; then update_bb.sh elif [ "${shortname}" == "ut99" ]; then update_ut99.sh elif [ "${shortname}" == "xnt" ]; then update_xnt.sh +elif [ "${shortname}" == "qw" ]; then + update_qw.sh elif [ "${shortname}" == "etl" ]; then update_etl.sh else update_steamcmd.sh fi +if { [ "${shortname}" == "arma3" ] || [ "${shortname}" == "dayz" ] || [ "${shortname}" == "bt" ] || [ "${shortname}" == "col" ] || [ "${shortname}" == "hw" ] || [ "${shortname}" == "l4d2" ] || [ "${shortname}" == "ohd" ] || [ "${shortname}" == "sb" ] || [ "${shortname}" == "squad" ] || [ "${shortname}" == "squad44" ] || [ "${shortname}" == "sol" ] || [ "${shortname}" == "st" ]; } && { [ -n "${workshopmods}" ] || [ -f "${datadir}/${selfname}-workshop.txt" ]; }; then + workshop_core.sh + fn_workshop_update +fi + core_exit.sh diff --git a/lgsm/modules/command_dev_parse_distro_details.sh b/lgsm/modules/command_dev_parse_distro_details.sh index dfb68ba2bf..2f3ec74ffb 100755 --- a/lgsm/modules/command_dev_parse_distro_details.sh +++ b/lgsm/modules/command_dev_parse_distro_details.sh @@ -27,7 +27,10 @@ declare -A server_details=( ['Backup Last']="${lastbackup}" ['CPU Average Load']="${load}" ['CPU Cores']="${cpucores}" - ['CPU Frequency']="${cpufreqency}" + ['CPU Cores Display']="${cpuphysicalcoresdisplay}" + ['CPU Logical CPUs']="${cpulogicalcores}" + ['CPU Average Frequency']="${cpufrequencyaveragedisplay}" + ['CPU Frequency Range']="${cpufrequencydisplay}" ['CPU Model']="${cpumodel}" ['Distro Codename']="${distrocodename}" ['Distro ID Like']="${distroidlike}" diff --git a/lgsm/modules/command_dev_parse_game_details.sh b/lgsm/modules/command_dev_parse_game_details.sh index 893785ff3d..f9903dec18 100755 --- a/lgsm/modules/command_dev_parse_game_details.sh +++ b/lgsm/modules/command_dev_parse_game_details.sh @@ -77,12 +77,14 @@ declare -A server_details=( ['Max Players']="${maxplayers}" ['Mod Server Port']="${modserverport}" ['OldQueryPortNumber']="${oldqueryportnumber}" + ['Owner ID']="${ownerid}" ['Port 401']="${port401}" ['Port IPv6']="${portipv6}" ['Port']="${port}" ['Query Enabled']="${queryenabled}" ['Query HTTP Port']="${httpqueryport}" ['Query HTTPS Port']="${httpsqueryport}" + ['Query IP']="${configqueryip}" ['Query Mode']="${querymode}" ['Query Port GS']="${gamespyqueryport}" ['Query Port']="${queryport}" diff --git a/lgsm/modules/command_fastdl.sh b/lgsm/modules/command_fastdl.sh index dfdcc9ec8f..f9c3e64cc9 100755 --- a/lgsm/modules/command_fastdl.sh +++ b/lgsm/modules/command_fastdl.sh @@ -21,6 +21,17 @@ luasvautorundir="${systemdir}/lua/autorun/server" luafastdlfile="lgsm_cl_force_fastdl.lua" luafastdlfullpath="${luasvautorundir}/${luafastdlfile}" +# File lists. +fastdlfilelist="${tmpdir}/fastdl_files.txt" +fastdlduplicatelist="${tmpdir}/fastdl_files_duplicate.txt" +fastdlnewrecord="${tmpdir}/fastdl_record.txt" +fastdlrecord="${datadir}/${selfname}-fastdl.txt" +fastdlclientlist="${tmpdir}/fastdl_files_client.txt" +fastdlupdatelist="${tmpdir}/fastdl_files_to_update.txt" +fastdlremovelist="${tmpdir}/fastdl_files_to_remove.txt" +fastdlcompresslist="${tmpdir}/fastdl_files_to_compress.txt" +fastdlmaxcompresssize="157286400" + # Header fn_print_header fn_print_nl "More info: ${italic}https://docs.linuxgsm.com/commands/fastdl" @@ -30,15 +41,17 @@ fn_print_nl "" fn_print_nl "${bold}${lightyellow}${commandaction} Setup" fn_messages_separator -# Prompt for clearing old files if directory was already here. +# Prompt for a full rebuild if directory was already here. +fastdlrebuild="off" if [ -d "${fastdldir}" ]; then - fn_print_warning_nl "Fastdl directory already exists." + fn_print_info_nl "Fastdl directory already exists, only changed files will be updated." fn_print_nl "${fastdldir}" fn_print_nl "" - if fn_prompt_yn "Overwrite existing directory?" Y; then - fn_script_log_info "Overwrite existing directory: YES" + if fn_prompt_yn "Rebuild Fastdl directory from scratch? This deletes everything in it." N; then + fastdlrebuild="on" + fn_script_log_info "Rebuild Fastdl directory from scratch: YES" else - core_exit.sh + fn_script_log_info "Rebuild Fastdl directory from scratch: NO" fi fi @@ -50,7 +63,7 @@ if [ "${shortname}" == "gmod" ]; then fn_script_log_info "Force clients to download files: YES" else luaresource="off" - fn_script_log_info "Force clients to download filesr: NO" + fn_script_log_info "Force clients to download files: NO" fi fi @@ -132,242 +145,350 @@ fn_human_readable_file_size() { fi } -# Provides info about the fastdl directory content and prompts for confirmation. -fn_fastdl_preview() { - # Remove any file list. - if [ -f "${tmpdir}/fastdl_files_to_compress.txt" ]; then - rm -f "${tmpdir:?}/fastdl_files_to_compress.txt" +# Sets the GoldSrc file types to include for the current directory. +fn_fastdl_goldsrc_extensions() { + fastdl_find_maxdepth=() + if [ "${directory}" == "." ]; then + allowed_extentions_array=("*.wad") + fastdl_find_maxdepth=("-maxdepth" "1") + elif [ "${directory}" == "maps" ]; then + allowed_extentions_array=("*.bsp" "*.res" "*.txt") + elif [ "${directory}" == "models" ]; then + allowed_extentions_array=("*.mdl") + elif [ "${directory}" == "sound" ]; then + allowed_extentions_array=("*.wav") + elif [ "${directory}" == "sprites" ]; then + allowed_extentions_array=("*.spr" "*.txt") + elif [ "${directory}" == "gfx" ]; then + allowed_extentions_array=("*.tga" "*.bmp") + elif [ "${directory}" == "overviews" ]; then + allowed_extentions_array=("*.bmp" "*.tga" "*.txt") fi - fn_print_nl "analysing required files" - fn_script_log_info "Analysing required files" - # Garry's Mod - if [ "${shortname}" == "gmod" ]; then - cd "${systemdir}" || exit - allowed_extentions_array=("*.ain" "*.bsp" "*.mdl" "*.mp3" "*.ogg" "*.otf" "*.pcf" "*.phy" "*.png" "*.svg" "*.vtf" "*.vmt" "*.vtx" "*.vvd" "*.ttf" "*.wav") - for allowed_extention in "${allowed_extentions_array[@]}"; do - fileswc=0 +} + +# Sets the Source file types to include for the current directory. +fn_fastdl_source_extensions() { + fastdl_find_maxdepth=() + if [ "${directory}" == "maps" ]; then + allowed_extentions_array=("*.bsp" "*.ain" "*.nav" "*.jpg" "*.txt") + elif [ "${directory}" == "materials" ]; then + allowed_extentions_array=("*.vtf" "*.vmt" "*.vbf" "*.png" "*.svg") + elif [ "${directory}" == "models" ]; then + allowed_extentions_array=("*.vtx" "*.vvd" "*.mdl" "*.phy" "*.jpg" "*.png" "*.vmt" "*.vtf") + elif [ "${directory}" == "particles" ]; then + allowed_extentions_array=("*.pcf") + elif [ "${directory}" == "sound" ]; then + allowed_extentions_array=("*.wav" "*.mp3" "*.ogg") + elif [ "${directory}" == "resource" ]; then + allowed_extentions_array=("*") + fi +} + +# Adds the allowed files in a content directory to the file list. +fn_fastdl_gather() { + local basedir="${1}" + local priority="${2}" + local label="${directory}" + if [ "${basedir}" != "${systemdir}" ]; then + label="${basedir#"${systemdir}/"}/${directory}" + fi + for allowed_extention in "${allowed_extentions_array[@]}"; do + fileswc=0 + if [ -z "${plainoutput}" ]; then tput sc - while read -r ext; do - ((fileswc++)) + fi + while IFS=$'\t' read -r filesize filemtime fastdlfile; do + ((fileswc++)) + if [ -z "${plainoutput}" ]; then + tput rc + tput el + fn_print "gathering ${label} ${allowed_extention} : ${fileswc}" + fi + fastdlrelpath="${fastdlfile#"${basedir}/"}" + printf '%s\t%s\t%s\t%s\t%s\n' "${priority}" "${fastdlrelpath#./}" "${filesize}" "${filemtime}" "${fastdlfile}" >> "${fastdlfilelist}" + done < <(find "${basedir}/${directory}" "${fastdl_find_maxdepth[@]}" -type f -iname "${allowed_extention}" -printf '%s\t%T@\t%p\n') + if [ -z "${plainoutput}" ]; then + tput rc + tput el + fi + fn_print "gathering ${label} ${allowed_extention} : ${fileswc}" + if [ ${fileswc} != 0 ]; then + fn_print_ok_eol_nl + else + fn_print_info_eol_nl + fi + done +} + +# Adds Garry's Mod files to the file list. +fn_fastdl_gather_gmod() { + cd "${systemdir}" || exit + allowed_extentions_array=("*.ain" "*.bsp" "*.mdl" "*.mp3" "*.ogg" "*.otf" "*.pcf" "*.phy" "*.png" "*.svg" "*.vtf" "*.vmt" "*.vtx" "*.vvd" "*.ttf" "*.wav") + for allowed_extention in "${allowed_extentions_array[@]}"; do + fileswc=0 + if [ -z "${plainoutput}" ]; then + tput sc + fi + while IFS=$'\t' read -r filesize filemtime fastdlfile; do + ((fileswc++)) + if [ -z "${plainoutput}" ]; then tput rc tput el fn_print "gathering ${allowed_extention} : ${fileswc}" - echo -e "${ext}" >> "${tmpdir}/fastdl_files_to_compress.txt" - done < <(find . -type f -iname "${allowed_extention}") - if [ ${fileswc} != 0 ]; then - fn_print_ok_eol_nl - else - fn_print_skip_eol_nl fi + fastdlrelpath="${fastdlfile#./}" + priority="2" + if [[ "${fastdlrelpath}" == addons/* ]]; then + addonname="${fastdlrelpath#addons/}" + addonname="${addonname%%/*}" + if [ "addons/${addonname}" == "${fastdlrelpath}" ]; then + continue + fi + priority="1:${addonname}" + fastdlrelpath="${fastdlrelpath#addons/"${addonname}"/}" + fi + printf '%s\t%s\t%s\t%s\t%s\n' "${priority}" "${fastdlrelpath}" "${filesize}" "${filemtime}" "${systemdir}/${fastdlfile#./}" >> "${fastdlfilelist}" + if [[ "${fastdlrelpath}" == lua/* ]]; then + printf '%s\t%s\t%s\t%s\t%s\n' "0" "${fastdlrelpath#lua/}" "${filesize}" "${filemtime}" "${systemdir}/${fastdlfile#./}" >> "${fastdlfilelist}" + fi + done < <(find . -type f -iname "${allowed_extention}" -printf '%s\t%T@\t%p\n') + if [ -z "${plainoutput}" ]; then + tput rc + tput el + fi + fn_print "gathering ${allowed_extention} : ${fileswc}" + if [ ${fileswc} != 0 ]; then + fn_print_ok_eol_nl + else + fn_print_skip_eol_nl + fi + done +} + +# Works out which files need to be copied, compressed or removed. +fn_fastdl_plan() { + LC_ALL=C sort -t $'\t' -k2,2 -k1,1 "${fastdlfilelist}" | awk -F '\t' -v dupes="${fastdlduplicatelist}" 'seen[$2]++ { print $5 " > " $2 > dupes; next } { print }' > "${fastdlfilelist}.sorted" + mv -f "${fastdlfilelist}.sorted" "${fastdlfilelist}" + if [ -f "${fastdlduplicatelist}" ]; then + duplicatefiles=$(wc -l < "${fastdlduplicatelist}") + while read -r duplicatefile; do + fn_script_log_info "Skipping ${duplicatefile}, already provided by a higher priority path" + done < "${fastdlduplicatelist}" + fi + + declare -A fastdlrecordsource=() + declare -A fastdlexpected=() + if [ "${fastdlrebuild}" != "on" ] && [ -f "${fastdlrecord}" ] && [ "$(head -n 1 "${fastdlrecord}")" == "${fastdldir}" ]; then + while IFS=$'\t' read -r fastdltarget recordsource; do + [ -n "${fastdltarget}" ] && fastdlrecordsource["${fastdltarget}"]="${recordsource}" + done < <(tail -n +2 "${fastdlrecord}") + fi + echo "${fastdldir}" > "${fastdlnewrecord}" + + read -ra fastdlexcludearray <<< "${fastdlexclude}" + while IFS=$'\t' read -r priority fastdlrelpath filesize filemtime fastdlfile; do + for excludepath in "${fastdlexcludearray[@]}"; do + # shellcheck disable=SC2254 + case "${fastdlrelpath}" in + ${excludepath#/}*) + ((excludedfiles++)) + continue 2 + ;; + esac done - # Source engine + if [ "${engine}" == "goldsrc" ] || [ "${filesize}" -gt "${fastdlmaxcompresssize}" ]; then + fastdlmode="copy" + fastdltarget="${fastdlrelpath}" + if [ "${engine}" != "goldsrc" ]; then + ((largefiles++)) + fi + else + fastdlmode="compress" + fastdltarget="${fastdlrelpath}.bz2" + fi + fastdlsource="${fastdlfile}"$'\t'"${filesize}"$'\t'"${filemtime}" + fastdlexpected["${fastdltarget}"]="on" + printf '%s\t%s\n' "${fastdltarget}" "${fastdlsource}" >> "${fastdlnewrecord}" + echo "${fastdlrelpath}" >> "${fastdlclientlist}" + if [ ! -f "${fastdldir}/${fastdltarget}" ] || [ "${fastdlrecordsource["${fastdltarget}"]}" != "${fastdlsource}" ]; then + printf '%s\t%s\t%s\n' "${fastdlmode}" "${fastdlrelpath}" "${fastdlfile}" >> "${fastdlupdatelist}" + ((updatefiles++)) + filesizetotal=$((filesizetotal + filesize)) + if [ "${fastdlmode}" == "compress" ]; then + ((compressfiles++)) + fi + else + ((unchangedfiles++)) + fi + done < "${fastdlfilelist}" + + for fastdltarget in "${!fastdlrecordsource[@]}"; do + if [ -z "${fastdlexpected["${fastdltarget}"]}" ] && [ -f "${fastdldir}/${fastdltarget}" ]; then + echo "${fastdltarget}" >> "${fastdlremovelist}" + ((removefiles++)) + fi + done + if [ -d "${fastdldir}" ] && [ "${fastdlrebuild}" != "on" ]; then + while read -r fastdltarget; do + if [ -z "${fastdlexpected["${fastdltarget}"]}" ] && [ -z "${fastdlrecordsource["${fastdltarget}"]}" ]; then + ((untrackedfiles++)) + fi + done < <(find "${fastdldir}" -type f -printf '%P\n') + fi +} + +# Provides info about the fastdl directory content and prompts for confirmation. +fn_fastdl_preview() { + # Remove any file list. + rm -f "${fastdlfilelist:?}" "${fastdlduplicatelist:?}" "${fastdlnewrecord:?}" "${fastdlclientlist:?}" "${fastdlupdatelist:?}" "${fastdlremovelist:?}" "${fastdlcompresslist:?}" + touch "${fastdlclientlist}" + totalfiles=0 + untrackedfiles=0 + duplicatefiles=0 + excludedfiles=0 + largefiles=0 + updatefiles=0 + compressfiles=0 + unchangedfiles=0 + removefiles=0 + filesizetotal=0 + fn_print_nl "analysing required files" + fn_script_log_info "Analysing required files" + # Garry's Mod + if [ "${shortname}" == "gmod" ]; then + fn_fastdl_gather_gmod + # Source and GoldSrc engines else - fastdl_directories_array=("maps" "materials" "models" "particles" "sound" "resources") + if [ "${engine}" == "goldsrc" ]; then + fastdl_directories_array=("." "maps" "models" "sound" "sprites" "gfx" "overviews") + else + fastdl_directories_array=("maps" "materials" "models" "particles" "sound" "resource") + fi + fastdl_custom_array=() + if [ "${engine}" == "source" ] && [ -d "${systemdir}/custom" ]; then + while IFS= read -r -d '' customdir; do + fastdl_custom_array+=("${customdir}") + done < <(find "${systemdir}/custom" -mindepth 1 -maxdepth 1 -type d -print0 | LC_ALL=C sort -z) + fi for directory in "${fastdl_directories_array[@]}"; do - if [ -d "${systemdir}/${directory}" ]; then - if [ "${directory}" == "maps" ]; then - local allowed_extentions_array=("*.bsp" "*.ain" "*.nav" "*.jpg" "*.txt") - elif [ "${directory}" == "materials" ]; then - local allowed_extentions_array=("*.vtf" "*.vmt" "*.vbf" "*.png" "*.svg") - elif [ "${directory}" == "models" ]; then - local allowed_extentions_array=("*.vtx" "*.vvd" "*.mdl" "*.phy" "*.jpg" "*.png" "*.vmt" "*.vtf") - elif [ "${directory}" == "particles" ]; then - local allowed_extentions_array=("*.pcf") - elif [ "${directory}" == "sound" ]; then - local allowed_extentions_array=("*.wav" "*.mp3" "*.ogg") + if [ "${engine}" == "goldsrc" ]; then + fn_fastdl_goldsrc_extensions + else + fn_fastdl_source_extensions + fi + for customdir in "${fastdl_custom_array[@]}"; do + if [ -d "${customdir}/${directory}" ]; then + fn_fastdl_gather "${customdir}" "0:${customdir##*/}" fi - for allowed_extention in "${allowed_extentions_array[@]}"; do - fileswc=0 - tput sc - while read -r ext; do - ((fileswc++)) - tput rc - tput el - fn_print "gathering ${directory} ${allowed_extention} : ${fileswc}" - echo -e "${ext}" >> "${tmpdir}/fastdl_files_to_compress.txt" - done < <(find "${systemdir}/${directory}" -type f -iname "${allowed_extention}") - tput rc - tput el - fn_print "gathering ${directory} ${allowed_extention} : ${fileswc}" - if [ ${fileswc} != 0 ]; then - fn_print_ok_eol_nl - else - fn_print_info_eol_nl - fi - done + done + if [ -d "${systemdir}/${directory}" ]; then + fn_fastdl_gather "${systemdir}" "1" fi done fi - if [ -f "${tmpdir}/fastdl_files_to_compress.txt" ]; then - fn_print_nl "calculating total file size" + if [ -f "${fastdlfilelist}" ]; then + fn_print_nl "calculating changes" fn_sleep_time_1 - totalfiles=$(wc -l < "${tmpdir}/fastdl_files_to_compress.txt") - # Calculates total file size. - while read -r dufile; do - filesize=$(stat -c %s "${dufile}") - filesizetotal=$((filesizetotal + filesize)) - exitcode=$? - if [ "${exitcode}" -ne 0 ]; then - fn_print_fail_eol_nl - fn_script_log_fail "Calculating total file size" - core_exit.sh - fi - done < "${tmpdir}/fastdl_files_to_compress.txt" + totalfiles=$(wc -l < "${fastdlfilelist}") + fn_fastdl_plan else fn_print_fail_eol_nl "generating file list" fn_script_log_fail "Generating file list." core_exit.sh fi - if [ "${engine}" == "source" ]; then - echo -e "about to compress ${totalfiles} files, total size $(fn_human_readable_file_size "${filesizetotal}" 0)" - elif [ "${engine}" == "goldsrc" ]; then - echo -e "about to copy ${totalfiles} files, total size $(fn_human_readable_file_size "${filesizetotal}" 0)" + echo -e "found ${totalfiles} files: ${unchangedfiles} unchanged, ${excludedfiles} excluded, ${duplicatefiles} duplicate" + if [ "${updatefiles}" -gt 0 ]; then + if [ "${engine}" == "source" ]; then + echo -e "about to update ${updatefiles} files, ${compressfiles} to compress, total size $(fn_human_readable_file_size "${filesizetotal}" 0)" + elif [ "${engine}" == "goldsrc" ]; then + echo -e "about to copy ${updatefiles} files, total size $(fn_human_readable_file_size "${filesizetotal}" 0)" + fi + fi + if [ "${largefiles}" -gt 0 ]; then + echo -e "${largefiles} files over 150 MB will be copied without compression" + fi + if [ "${removefiles}" -gt 0 ]; then + echo -e "about to remove ${removefiles} files no longer on the server" + fi + if [ "${untrackedfiles}" -gt 0 ]; then + echo -e "${untrackedfiles} files in the Fastdl directory were not added by ${selfname} and will be left alone" + fi + if [ "${updatefiles}" -eq 0 ] && [ "${removefiles}" -eq 0 ]; then + echo -e "Fastdl directory is up to date" fi - fn_script_log_info "${totalfiles} files, total size $(fn_human_readable_file_size "${filesizetotal}" 0)" - rm -f "${tmpdir:?}/fastdl_files_to_compress.txt" + fn_script_log_info "${totalfiles} files, ${updatefiles} to update, ${unchangedfiles} unchanged, ${excludedfiles} excluded, ${removefiles} to remove, total size $(fn_human_readable_file_size "${filesizetotal}" 0)" if ! fn_prompt_yn "Continue?" Y; then exitcode=0 core_exit.sh fi } -# Builds Garry's Mod fastdl directory content. -fn_fastdl_gmod() { - cd "${systemdir}" || exit - for allowed_extention in "${allowed_extentions_array[@]}"; do - fileswc=0 - tput sc - while read -r fastdlfile; do - ((fileswc++)) - tput rc - tput el - fn_print "copying ${allowed_extention} : ${fileswc}" - cp --parents "${fastdlfile}" "${fastdldir}" +# Removes files from the fastdl directory that are no longer on the server. +fn_fastdl_remove() { + if [ -s "${fastdlremovelist}" ]; then + fn_print "removing ${removefiles} files no longer on the server" + while read -r fastdlstalefile; do + rm -f "${fastdldir:?}/${fastdlstalefile}" exitcode=$? if [ "${exitcode}" -ne 0 ]; then fn_print_fail_eol_nl - fn_script_log_fail "Copying ${fastdlfile} > ${fastdldir}" + fn_script_log_fail "Removing ${fastdldir}/${fastdlstalefile}" core_exit.sh else - fn_script_log_pass "Copying ${fastdlfile} > ${fastdldir}" + fn_script_log_pass "Removing ${fastdldir}/${fastdlstalefile}" fi - done < <(find . -type f -iname "${allowed_extention}") - if [ ${fileswc} != 0 ]; then - fn_print_ok_eol_nl - fi - done - # Correct addons directory structure for Fastdl. - if [ -d "${fastdldir}/addons" ]; then - fn_print "updating addons file structure..." - cp -Rf "${fastdldir}"/addons/*/* "${fastdldir}" - exitcode=$? - if [ "${exitcode}" -ne 0 ]; then - fn_print_fail_eol_nl - fn_script_log_fail "Updating addons file structure" - core_exit.sh - else - fn_print_ok_eol_nl - fn_script_log_pass "Updating addons file structure" - fi - # Clear addons directory in fastdl. - fn_print "clearing addons dir from fastdl dir..." - fn_sleep_time_1 - rm -rf "${fastdldir:?}/addons" - exitcode=$? - if [ "${exitcode}" -ne 0 ]; then - fn_print_fail_eol_nl - fn_script_log_fail "Clearing addons dir from fastdl dir" - core_exit.sh - else - fn_print_ok_eol_nl - fn_script_log_pass "Clearing addons dir from fastdl dir" - fi - fi - # Correct content that may be into a lua directory by mistake like some darkrpmodification addons. - if [ -d "${fastdldir}/lua" ]; then - fn_print "correcting DarkRP files..." - fn_sleep_time_1 - cp -Rf "${fastdldir}/lua/"* "${fastdldir}" - exitcode=$? - if [ "${exitcode}" -ne 0 ]; then - fn_print_fail_eol_nl - fn_script_log_fail "Correcting DarkRP files" - core_exit.sh - else - fn_print_ok_eol_nl - fn_script_log_pass "Correcting DarkRP files" - fi - fi - if [ -f "${tmpdir}/fastdl_files_to_compress.txt" ]; then - totalfiles=$(wc -l < "${tmpdir}/fastdl_files_to_compress.txt") - # Calculates total file size. - while read -r dufile; do - filesize=$(du -b "${dufile}" | awk '{ print $1 }') - filesizetotal=$((filesizetotal + filesize)) - done < "${tmpdir}/fastdl_files_to_compress.txt" + done < "${fastdlremovelist}" + find "${fastdldir:?}" -mindepth 1 -type d -empty -delete + fn_print_ok_eol_nl fi } -fn_fastdl_source() { - for directory in "${fastdl_directories_array[@]}"; do - if [ -d "${systemdir}/${directory}" ]; then - if [ "${directory}" == "maps" ]; then - local allowed_extentions_array=("*.bsp" "*.ain" "*.nav" "*.jpg" "*.txt") - elif [ "${directory}" == "materials" ]; then - local allowed_extentions_array=("*.vtf" "*.vmt" "*.vbf" "*.png" "*.svg") - elif [ "${directory}" == "models" ]; then - local allowed_extentions_array=("*.vtx" "*.vvd" "*.mdl" "*.phy" "*.jpg" "*.png") - elif [ "${directory}" == "particles" ]; then - local allowed_extentions_array=("*.pcf") - elif [ "${directory}" == "sound" ]; then - local allowed_extentions_array=("*.wav" "*.mp3" "*.ogg") +# Copies new and changed files to the fastdl directory. +fn_fastdl_copy() { + if [ -s "${fastdlupdatelist}" ]; then + fileswc=0 + if [ -z "${plainoutput}" ]; then + tput sc + fi + while IFS=$'\t' read -r fastdlmode fastdlrelpath fastdlfile; do + ((fileswc++)) + if [ -z "${plainoutput}" ]; then + tput rc + tput el + fn_print "copying files : ${fileswc}/${updatefiles}" fi - for allowed_extention in "${allowed_extentions_array[@]}"; do - fileswc=0 - tput sc - while read -r fastdlfile; do - ((fileswc++)) - tput rc - tput el - fn_print "copying ${directory} ${allowed_extention} : ${fileswc}" - fn_sleep_time - # get relative path of file in the dir - tmprelfilepath="${fastdlfile#"${systemdir}/"}" - copytodir="${tmprelfilepath%/*}" - # create relative path for fastdl - if [ ! -d "${fastdldir}/${copytodir}" ]; then - mkdir -p "${fastdldir}/${copytodir}" - fi - cp "${fastdlfile}" "${fastdldir}/${copytodir}" - exitcode=$? - if [ "${exitcode}" -ne 0 ]; then - fn_print_fail_eol_nl - fn_script_log_fail "Copying ${fastdlfile} > ${fastdldir}/${copytodir}" - core_exit.sh - else - fn_script_log_pass "Copying ${fastdlfile} > ${fastdldir}/${copytodir}" - fi - done < <(find "${systemdir}/${directory}" -type f -iname "${allowed_extention}") - if [ ${fileswc} != 0 ]; then - fn_print_ok_eol_nl - fi - done + fastdltarget="${fastdldir}/${fastdlrelpath}" + mkdir -p "${fastdltarget%/*}" && cp -p "${fastdlfile}" "${fastdltarget}" + exitcode=$? + if [ "${exitcode}" -ne 0 ]; then + fn_print_fail_eol_nl + fn_script_log_fail "Copying ${fastdlfile} > ${fastdltarget}" + core_exit.sh + else + fn_script_log_pass "Copying ${fastdlfile} > ${fastdltarget}" + fi + if [ "${fastdlmode}" == "compress" ]; then + printf '%s\0' "${fastdltarget}" >> "${fastdlcompresslist}" + fi + done < "${fastdlupdatelist}" + if [ -n "${plainoutput}" ]; then + fn_print "copying files : ${fileswc}/${updatefiles}" fi - done + fn_print_ok_eol_nl + fi } # Builds the fastdl directory content. fn_fastdl_build() { # Copy all needed files for Fastdl. - fn_print_nl "copying files to ${fastdldir}" - fn_script_log_info "Copying files to ${fastdldir}" + fn_print_nl "updating files in ${fastdldir}" + fn_script_log_info "Updating files in ${fastdldir}" + fn_fastdl_remove + fn_fastdl_copy if [ "${shortname}" == "gmod" ]; then - fn_fastdl_gmod fn_fastdl_gmod_dl_enforcer - else - fn_fastdl_source fi } @@ -394,7 +515,7 @@ fn_fastdl_gmod_dl_enforcer() { # Read all filenames and put them into a lua file at the right path. while read -r line; do echo -e "resource.AddFile( \"${line}\" )" >> "${luafastdlfullpath}" - done < <(find "${fastdldir:?}" \( -type f ! -name "*.bz2" \) -printf '%P\n') + done < "${fastdlclientlist}" exitcode=$? if [ "${exitcode}" -ne 0 ]; then fn_print_fail_eol_nl @@ -409,30 +530,61 @@ fn_fastdl_gmod_dl_enforcer() { # Compresses Fastdl files using bzip2. fn_fastdl_bzip2() { - while read -r filetocompress; do - fn_print "compressing ${filetocompress}" - bzip2 -f "${filetocompress}" - exitcode=$? - if [ "${exitcode}" -ne 0 ]; then + if [ -s "${fastdlcompresslist}" ]; then + fastdlthreads="$(nproc)" + fn_print "compressing ${compressfiles} files using ${fastdlthreads} threads" + xargs -0 -r -n 1 -P "${fastdlthreads}" bzip2 -f < "${fastdlcompresslist}" + compressexitcode=$? + while IFS=$'\t' read -r fastdlmode fastdlrelpath fastdlfile; do + if [ "${fastdlmode}" == "compress" ]; then + filetocompress="${fastdldir}/${fastdlrelpath}" + if [ -f "${filetocompress}.bz2" ] && [ ! -f "${filetocompress}" ]; then + fn_script_log_pass "Compressing ${filetocompress}" + else + fn_script_log_fail "Compressing ${filetocompress}" + fi + fi + done < "${fastdlupdatelist}" + if [ "${compressexitcode}" -ne 0 ]; then fn_print_fail_eol_nl - fn_script_log_fail "Compressing ${filetocompress}" + fn_script_log_fail "Compressing files" + exitcode=1 core_exit.sh else fn_print_ok_eol_nl - fn_script_log_pass "Compressing ${filetocompress}" + fn_script_log_pass "Compressing files" fi - done < <(find "${fastdldir:?}" \( -type f ! -name "*.bz2" \)) + fi +} + +# Saves the list of files written to the fastdl directory. +fn_fastdl_record() { + fn_print "saving Fastdl file record ${fastdlrecord}" + mkdir -p "${datadir}" && mv -f "${fastdlnewrecord}" "${fastdlrecord}" + exitcode=$? + if [ "${exitcode}" -ne 0 ]; then + fn_print_fail_eol_nl + fn_script_log_fail "Saving Fastdl file record ${fastdlrecord}" + core_exit.sh + else + fn_print_ok_eol_nl + fn_script_log_pass "Saving Fastdl file record ${fastdlrecord}" + fi } check.sh # Run functions. fn_fastdl_preview -fn_clear_old_fastdl +if [ "${fastdlrebuild}" == "on" ]; then + fn_clear_old_fastdl +fi fn_fastdl_dirs fn_fastdl_build if [ "${engine}" == "source" ]; then fn_fastdl_bzip2 fi +fn_fastdl_record +rm -f "${fastdlfilelist:?}" "${fastdlduplicatelist:?}" "${fastdlnewrecord:?}" "${fastdlclientlist:?}" "${fastdlupdatelist:?}" "${fastdlremovelist:?}" "${fastdlcompresslist:?}" # Finished message. fn_print_nl "Fastdl files are located in:" fn_print_nl "${fastdldir}" diff --git a/lgsm/modules/command_install.sh b/lgsm/modules/command_install.sh index 8dc9a77df8..7918db4579 100755 --- a/lgsm/modules/command_install.sh +++ b/lgsm/modules/command_install.sh @@ -39,6 +39,8 @@ else install_gslt.sh elif [ "${shortname}" == "dst" ]; then install_dst_token.sh + elif [ "${shortname}" == "fivem" ]; then + install_fivem_license.sh elif [ "${shortname}" == "squad" ]; then install_squad_license.sh elif [ "${shortname}" == "ts3" ]; then diff --git a/lgsm/modules/command_install_resources_mta.sh b/lgsm/modules/command_install_resources_mta.sh index 7eca4fb979..72084f77ae 100755 --- a/lgsm/modules/command_install_resources_mta.sh +++ b/lgsm/modules/command_install_resources_mta.sh @@ -14,7 +14,7 @@ fn_install_resources() { echo -e "" echo -e "${bold}${lightyellow}Installing Default Resources${default}" fn_messages_separator - fn_fetch_file "http://mirror.mtasa.com/mtasa/resources/mtasa-resources-latest.zip" "" "" "" "${tmpdir}" "mtasa-resources-latest.zip" "nochmodx" "norun" "noforce" "nohash" + fn_fetch_file "https://mirror.multitheftauto.com/mtasa/resources/mtasa-resources-latest.zip" "" "" "" "${tmpdir}" "mtasa-resources-latest.zip" "nochmodx" "norun" "noforce" "nohash" fn_dl_extract "${tmpdir}" "mtasa-resources-latest.zip" "${resourcesdir}" echo -e "Default Resources Installed." } @@ -30,3 +30,8 @@ else fn_print_warning_nl "Default resources are not installed when using ./${selfname} auto-install." fn_print_information_nl "To install default resources use ./${selfname} install" fi + +if [ "${firstcommandname}" == "DEFAULT-RESOURCES" ]; then + exitcode=0 + core_exit.sh +fi diff --git a/lgsm/modules/command_mods_install.sh b/lgsm/modules/command_mods_install.sh index a8f90293b2..857bd347c5 100755 --- a/lgsm/modules/command_mods_install.sh +++ b/lgsm/modules/command_mods_install.sh @@ -64,7 +64,13 @@ echo -e "" while :; do echo -en "Enter an ${cyan}addon/mod${default} to ${green}install${default} (or exit to abort): " - read -r usermodselect + if ! read -r usermodselect && [ -z "${usermodselect}" ]; then + echo -e "" + fn_print_error_nl "Unable to read an addon/mod: no input available" + fn_script_log_error "Unable to read an addon/mod: no input available" + exitcode=2 + core_exit.sh + fi # Exit if user says exit or abort. if [ "${usermodselect}" == "exit" ] || [ "${usermodselect}" == "abort" ]; then core_exit.sh @@ -109,6 +115,16 @@ if [ -f "${modsinstalledlistfullpath}" ]; then fi ## Installation. +# CounterStrikeSharp requires Metamod:Source 2.0. +if [ "${modcommand}" == "counterstrikesharp" ]; then + fn_mod_exist "metamodsource2" +fi + +# MatchZy requires CounterStrikeSharp. +if [ "${modcommand}" == "matchzy" ]; then + fn_mod_exist "counterstrikesharp" +fi + # If amxmodx check if metamod exists first if [ "${modcommand}" == "amxmodx" ]; then fn_mod_exist "metamod" @@ -122,17 +138,31 @@ if [ "${modcommand}" == "amxmodxcs" ] \ fn_mod_exist "amxmodx" fi +# If nolobbyreservation check if sourcemod exists first as it is compiled using the SourceMod compiler +if [ "${modcommand}" == "nolobbyreservation" ]; then + fn_mod_exist "sourcemod" +fi + fn_create_mods_dir fn_mods_clear_tmp_dir fn_mods_create_tmp_dir fn_mod_install_files fn_mod_lowercase +# NoLobbyReservation is only distributed as source +if [ "${modcommand}" == "nolobbyreservation" ]; then + fn_mod_compile_sourcemod_plugin "nolobbyreservation" +fi fn_mod_create_filelist fn_mod_copy_destination fn_mod_add_list fn_mod_tidy_files_list fn_mods_clear_tmp_dir +# Install the Metamod:Source search path for CS2. +if [ "${modcommand}" == "metamodsource2" ]; then + fn_mod_install_gameinfo_gi_file +fi + # Create/modify existing liblist.gam file for Metamod if [ "${modcommand}" == "metamod" ]; then fn_mod_install_liblist_gam_file diff --git a/lgsm/modules/command_mods_remove.sh b/lgsm/modules/command_mods_remove.sh index 04240eb60d..ad3ee95279 100755 --- a/lgsm/modules/command_mods_remove.sh +++ b/lgsm/modules/command_mods_remove.sh @@ -35,7 +35,13 @@ echo -e "" while :; do echo -en "Enter an ${cyan}addon/mod${default} to ${red}remove${default} (or exit to abort): " - read -r usermodselect + if ! read -r usermodselect && [ -z "${usermodselect}" ]; then + echo -e "" + fn_print_error_nl "Unable to read an addon/mod: no input available" + fn_script_log_error "Unable to read an addon/mod: no input available" + exitcode=2 + core_exit.sh + fi # Exit if user says exit or abort. if [ "${usermodselect}" == "exit" ] || [ "${usermodselect}" == "abort" ]; then core_exit.sh @@ -76,7 +82,9 @@ echo -e "* location: ${modinstalldir}" fn_sleep_time_1 # Go through every file and remove it. modfileline="1" -tput sc +if [ -z "${plainoutput}" ]; then + tput sc +fi while [ "${modfileline}" -le "${modsfilelistsize}" ]; do # Current line defines current file to remove. currentfileremove=$(sed "${modfileline}q;d" "${modsdir}/${modcommand}-files.txt") @@ -92,8 +100,10 @@ while [ "${modfileline}" -le "${modsfilelistsize}" ]; do fn_script_log_pass "Removing ${modinstalldir}/${currentfileremove}" fi fi - tput rc - tput el + if [ -z "${plainoutput}" ]; then + tput rc + tput el + fi echo -e "removing ${modprettyname} ${modfileline} / ${modsfilelistsize} : ${currentfileremove}..." ((modfileline++)) done @@ -151,6 +161,11 @@ if [ "${engine}" == "unity3d" ] && [[ "${modprettyname}" == *"Oxide"* ]]; then unset exitbypass fi +# Remove the Metamod:Source search path for CS2. +if [ "${modcommand}" == "metamodsource2" ]; then + fn_mod_remove_gameinfo_gi_file +fi + # Remove/modify existing liblist.gam file for Metamod if [ "${modcommand}" == "metamod" ]; then fn_mod_remove_liblist_gam_file diff --git a/lgsm/modules/command_mods_update.sh b/lgsm/modules/command_mods_update.sh index 10279b67b3..e84db47ad1 100755 --- a/lgsm/modules/command_mods_update.sh +++ b/lgsm/modules/command_mods_update.sh @@ -88,11 +88,19 @@ while [ "${installedmodsline}" -le "${installedmodscount}" ]; do fn_mod_install_files fn_mod_lowercase fn_remove_cfg_files + # NoLobbyReservation is only distributed as source + if [ "${modcommand}" == "nolobbyreservation" ]; then + fn_mod_compile_sourcemod_plugin "nolobbyreservation" + fi fn_mod_create_filelist fn_mod_copy_destination fn_mod_add_list fn_mod_tidy_files_list fn_mods_clear_tmp_dir + # Restore the Metamod:Source search path if a CS2 update removed it. + if [ "${modcommand}" == "metamodsource2" ]; then + fn_mod_install_gameinfo_gi_file + fi fi ((installedmodsline++)) else diff --git a/lgsm/modules/command_monitor.sh b/lgsm/modules/command_monitor.sh index 0a80fcbf74..82a7227551 100755 --- a/lgsm/modules/command_monitor.sh +++ b/lgsm/modules/command_monitor.sh @@ -11,6 +11,12 @@ commandaction="Monitoring" moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_firstcommand_set +# Checks if this instance is running one of the given commands, e.g. "update|u". +# Matches the script run as ./gameserver, /path/to/gameserver or bash gameserver. +fn_monitor_command_running() { + [ "$(pgrep -fc -u "${USER}" "^([^ ]*/)?bash ([^ ]*/)?${selfname} ($1)( |$)")" != "0" ] +} + fn_monitor_check_monitoring() { if [ -f "${lockdir}/${selfname}.lock" ]; then # Part of migration to v23.5.0. #4296 @@ -30,7 +36,7 @@ fn_monitor_check_monitoring() { } fn_monitor_check_install() { - if [ "$(pgrep -fc -u "${USER}" "/bin/bash ./${selfname} install")" != "0" ] || [ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} i")" != "0" ] || [ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} auto-install")" != "0" ] || [ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} ai")" != "0" ]; then + if fn_monitor_command_running "install|i|auto-install|ai"; then fn_print_dots "Checking installer" fn_print_checking_eol fn_script_log_info "Checking installer: CHECKING" @@ -42,7 +48,7 @@ fn_monitor_check_install() { } fn_monitor_check_debug() { - if [ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} debug")" != "0" ] || [ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} d")" != "0" ]; then + if fn_monitor_command_running "debug|d"; then fn_print_dots "Checking debug" fn_print_checking_eol fn_print_info "Checking debug: Debug is running" @@ -53,7 +59,7 @@ fn_monitor_check_debug() { } fn_monitor_check_details() { - if [ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} details")" != "0" ] || [ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} dt")" != "0" ]; then + if fn_monitor_command_running "details|dt"; then fn_print_dots "Checking details" fn_print_checking_eol fn_print_info "Checking details: Details is running" @@ -76,12 +82,12 @@ fn_monitor_check_starting() { fi fi - if [ -f "${lockdir}/${selfname}-starting.lock" ] && [[ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} start")" != "0" || "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} s")" != "0" ]]; then + if [ -f "${lockdir}/${selfname}-starting.lock" ] && fn_monitor_command_running "start|st"; then fn_print_dots "Checking start" fn_print_checking_eol fn_print_info "Checking start: LinuxGSM is starting" fn_print_info_eol_nl - fn_script_log_info "Checking backup: LinuxGSM is starting" + fn_script_log_info "Checking start: LinuxGSM is starting" core_exit.sh fi } @@ -99,12 +105,12 @@ fn_monitor_check_stopping() { fi fi - if [ -f "${lockdir}/${selfname}-stopping.lock" ] && [[ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} stop")" != "0" || "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} s")" != "0" ]]; then + if [ -f "${lockdir}/${selfname}-stopping.lock" ] && fn_monitor_command_running "stop|sp"; then fn_print_dots "Checking stop" fn_print_checking_eol fn_print_info "Checking stop: LinuxGSM is stopping" fn_print_info_eol_nl - fn_script_log_info "Checking backup: LinuxGSM is stopping" + fn_script_log_info "Checking stop: LinuxGSM is stopping" core_exit.sh fi } @@ -129,9 +135,73 @@ fn_monitor_check_restart_request() { fi } +# An update postponed because players were online runs once the server is empty. +# It runs in the background as its own update command, so monitor returns straight away +# (e.g. a healthcheck timeout can't stop it) and other monitor runs see the update in progress. +fn_monitor_check_update_request() { + local updaterequest="${lockdir}/${selfname}-update-request.lock" + if [ -f "${updaterequest}" ]; then + fn_print_dots "Checking update: " + fn_print_checking_eol + fn_print_info "Checking update: Update requested: " + fn_print_info_eol_nl + fn_script_log_info "Checking update: Update requested" + check_players_online.sh + if [ -n "${playersonline}" ]; then + fn_print_info_nl "${playersonline} players are on the server: update postponed" + fn_script_log_info "${playersonline} players are on the server: update postponed" + echo "${playersonline}" > "${lockdir:?}/${selfname}-player-numbers.lock" + else + local requestforce="" + if grep -qx "force" "${updaterequest}"; then + requestforce="1" + fi + fn_print_info_nl "Checking update: Running requested update" + fn_script_log_info "Checking update: Running requested update" + forceupdate="${requestforce}" setsid "${rootdir}/${selfname}" update > /dev/null 2>&1 < /dev/null & + # shellcheck disable=SC2034 # Used by core_exit.sh. + exitcode=0 + core_exit.sh + fi + fi +} + +# A backup postponed because players were online runs once the server is empty, in the background +# like a requested update. An alert is sent once if it has been postponed for over 24 hours. +fn_monitor_check_backup_request() { + local backuprequest="${lockdir}/${selfname}-backup-request.lock" + if [ -f "${backuprequest}" ]; then + fn_print_dots "Checking backup: " + fn_print_checking_eol + fn_print_info "Checking backup: Backup requested: " + fn_print_info_eol_nl + fn_script_log_info "Checking backup: Backup requested" + check_players_online.sh + if [ -n "${playersonline}" ]; then + fn_print_info_nl "${playersonline} players are on the server: backup postponed" + fn_script_log_info "${playersonline} players are on the server: backup postponed" + echo "${playersonline}" > "${lockdir:?}/${selfname}-player-numbers.lock" + local requested + requested="$(head -n 1 "${backuprequest}")" + if [[ "${requested}" =~ ^[0-9]+$ ]] && [ "$(($(date '+%s') - requested))" -gt 86400 ] && ! grep -q "alerted" "${backuprequest}"; then + alert="backup-postponed" + alert.sh + echo "alerted" >> "${backuprequest}" + fi + else + fn_print_info_nl "Checking backup: Running requested backup" + fn_script_log_info "Checking backup: Running requested backup" + setsid "${rootdir}/${selfname}" backup > /dev/null 2>&1 < /dev/null & + # shellcheck disable=SC2034 # Used by core_exit.sh. + exitcode=0 + core_exit.sh + fi + fi +} + fn_monitor_check_backup() { - # Remove stale lockfile. - if [ -f "${lockdir}/backup.lock" ]; then + # Remove stale lockfile, unless a long backup is still running. + if [ -f "${lockdir}/backup.lock" ] && ! fn_monitor_command_running "backup|b"; then if [ "$(find "${lockdir}/backup.lock" -mmin +60)" ]; then fn_print_dots "Checking backup" fn_print_checking_eol @@ -142,7 +212,7 @@ fn_monitor_check_backup() { fi fi - if [ -f "${lockdir}/backup.lock" ] && [[ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} backup")" != "0" || "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} b")" != "0" ]]; then + if [ -f "${lockdir}/backup.lock" ] && fn_monitor_command_running "backup|b"; then fn_print_dots "Checking backup" fn_print_checking_eol fn_print_info "Checking backup: Backup is running" @@ -153,8 +223,8 @@ fn_monitor_check_backup() { } fn_monitor_check_update() { - # Remove stale lockfile. - if [ -f "${lockdir}/update.lock" ]; then + # Remove stale lockfile, unless a long update is still running. + if [ -f "${lockdir}/update.lock" ] && ! fn_monitor_command_running "update|u|validate|v|force-update|fu|update-restart|ur|workshop-update|wu"; then if [ "$(find "${lockdir}/update.lock" -mmin +15)" ]; then fn_print_dots "Checking update" fn_print_checking_eol @@ -165,7 +235,7 @@ fn_monitor_check_update() { fi fi - if [ -f "${lockdir}/update.lock" ] && [[ "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} update")" != "0" || "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} validate")" != "0" || "$(pgrep -fcx -u "${USER}" "/bin/bash ./${selfname} v")" != "0" || "$(pgrep -fc force-update "${USER}" "/bin/bash ./${selfname} fu")" != "0" ]]; then + if [ -f "${lockdir}/update.lock" ] && fn_monitor_command_running "update|u|validate|v|force-update|fu|update-restart|ur|workshop-update|wu"; then fn_print_dots "Checking update" fn_print_checking_eol fn_print_info "Checking update: LinuxGSM is updating the game server" @@ -175,6 +245,11 @@ fn_monitor_check_update() { fi } +fn_monitor_check_backup_update() { + fn_monitor_check_backup + fn_monitor_check_update +} + # Source engine games may display a messages to indicate the server needs restarting. fn_monitor_check_update_source() { if [ -f "${consolelogdir}/${selfname}-console.log" ] && [ "${engine}" == "source" ]; then @@ -208,26 +283,29 @@ fn_monitor_check_session() { fn_script_log_error "Checking session: There are PIDS with identical tmux sessions running" fn_script_log_error "Checking session: Killing all tmux sessions with the socketname name ${socketname} and session name ${sessionname}" pkill -f "tmux -L ${socketname} new-session -d -x ${sessionwidth} -y ${sessionheight} -s ${sessionname}" + fn_monitor_check_backup_update command_restart.sh core_exit.sh # Check for tmux pids with the same tmux session and socket names. This will reduce issues with migration to release v23.5.0. #4296 - elif [ "$(pgrep -fc -u "${USER}" "tmux -L ${sessionname} new-session -d -x ${sessionwidth} -y ${sessionheight} -s ${sessionname}")" != "0" ]; then + elif [ "$(pgrep -fc -u "${USER}" "^tmux -L ${sessionname} new-session -d -x ${sessionwidth} -y ${sessionheight} -s ${sessionname}( |$)")" != "0" ]; then fn_print_error "Checking session: PIDS with the same tmux session and socket names are running" fn_print_error_eol_nl fn_script_log_error "Checking session: ERROR" fn_script_log_error "Checking session: PIDS with the same tmux session and socket names are running" fn_script_log_error "Checking session: Killing session with the socketname name ${sessionname} and session name ${sessionname}" - pkill -f "tmux -L ${sessionname} new-session -d -x ${sessionwidth} -y ${sessionheight} -s ${sessionname}" + pkill -f "^tmux -L ${sessionname} new-session -d -x ${sessionwidth} -y ${sessionheight} -s ${sessionname}( |$)" + fn_monitor_check_backup_update command_restart.sh core_exit.sh # Check for tmux pids that are using the old type of tmux session. This will reduce issues with migration to release v23.5.0. #4296 - elif [ "$(pgrep -fc -u "${USER}" "tmux new-session -d -x ${sessionwidth} -y ${sessionheight} -s ${sessionname}")" != "0" ]; then + elif [ "$(pgrep -fc -u "${USER}" "^tmux new-session -d -x ${sessionwidth} -y ${sessionheight} -s ${sessionname}( |$)")" != "0" ]; then fn_print_error "Checking session: PIDS with old type tmux session are running" fn_print_error_eol_nl fn_script_log_error "Checking session: ERROR" fn_script_log_error "Checking session: PIDS with old type tmux session are running" fn_script_log_error "Checking session: Killing session with the session name ${sessionname}" - pkill -f "tmux new-session -d -x ${sessionwidth} -y ${sessionheight} -s ${sessionname}" + pkill -f "^tmux new-session -d -x ${sessionwidth} -y ${sessionheight} -s ${sessionname}( |$)" + fn_monitor_check_backup_update command_restart.sh core_exit.sh elif [ "${status}" != "0" ]; then @@ -242,6 +320,7 @@ fn_monitor_check_session() { fn_print_error "Checking session" fn_print_fail_eol_nl fn_script_log_fail "Checking session: FAIL" + fn_monitor_check_backup_update alert="monitor-session" alert.sh fn_script_log_info "Checking session: Monitor is restarting ${selfname}" @@ -280,6 +359,51 @@ fn_query_tcp() { querystatus="$?" } +fn_monitor_query_port_hint() { + local sockets protocol state recvq sendq address peer details + local serverpid="" protocols="" process="" pid="" ancestor="" serverprocess="" otherprocess="" hint="" + + command -v ss > /dev/null 2>&1 || return 0 + sockets="$(ss -H -lntup 2> /dev/null)" || return 0 + serverpid="$(TERM=screen tmux -L "${socketname}" list-sessions -F "#{session_name} #{pane_pid}" 2> /dev/null | awk -v session="${sessionname}" '$1 == session {print $2}')" + + while read -r protocol state recvq sendq address peer details; do + if [ "${address##*:}" != "${queryport}" ]; then + continue + fi + if [[ " ${protocols//\// } " != *" ${protocol} "* ]]; then + protocols+="${protocols:+/}${protocol}" + fi + process="$(sed -nE 's/.*users:\(\("([^"]+)".*/\1/p' <<< "${details}")" + pid="$(sed -nE 's/.*users:\(\("[^"]+",pid=([0-9]+).*/\1/p' <<< "${details}")" + ancestor="${pid}" + while [ -n "${serverpid}" ] && [ -n "${ancestor}" ] && [ "${ancestor}" -gt 1 ]; do + if [ "${ancestor}" == "${serverpid}" ]; then + serverprocess="${process}" + break + fi + ancestor="$(ps -o ppid= -p "${ancestor}" 2> /dev/null | tr -d ' ')" + done + if [ -z "${serverprocess}" ] && [ -z "${otherprocess}" ]; then + otherprocess="${process}" + fi + done <<< "${sockets}" + + if [ -z "${protocols}" ]; then + hint="Nothing is listening on port ${queryport}; check the server started and the port settings" + elif [ -n "${serverprocess}" ]; then + hint="Port ${queryport}/${protocols} is open by the game server (${serverprocess}) but it did not answer; the server may be hung, or the query port or type may not match" + elif [ -n "${otherprocess}" ]; then + hint="Port ${queryport}/${protocols} is in use by another process (${otherprocess}); check for a port conflict" + else + hint="Port ${queryport}/${protocols} is in use by a process owned by another user; check for a port conflict" + fi + + fn_print_warn "Query port: ${hint}" + fn_print_warn_eol_nl + fn_script_log_warn "Query port: ${hint}" +} + fn_monitor_query() { # Will loop and query up to 5 times every 15 seconds. # Query will wait up to 60 seconds to confirm server is down as server can become non-responsive during map changes. @@ -291,9 +415,9 @@ fn_monitor_query() { fn_script_log_info "Querying port: ${querymethod}: ${queryip}:${queryport} : ${queryattempt} : QUERYING" # querydelay if [ "$(head -n 1 "${lockdir}/${selfname}-started.lock")" -gt "$(date "+%s" -d "${querydelay} mins ago")" ]; then - fn_print_ok "Querying port: ${querymethod}: ${ip}:${queryport} : ${totalseconds}/${queryattempt}" + fn_print_ok "Querying port: ${querymethod}: ${queryip}:${queryport} : ${totalseconds}/${queryattempt}" fn_print_delay_eol_nl - fn_script_log_info "Querying port: ${querymethod}: ${ip}:${queryport} : ${queryattempt} : DELAY" + fn_script_log_info "Querying port: ${querymethod}: ${queryip}:${queryport} : ${queryattempt} : DELAY" fn_script_log_info "Query bypassed: ${gameservername} started less than ${querydelay} minutes ago" fn_script_log_info "Server started: $(date -d "@$(head -n 1 "${lockdir}/${selfname}-started.lock")")" fn_script_log_info "Current time: $(date)" @@ -353,6 +477,8 @@ fn_monitor_query() { fn_print_fail "Querying port: ${querymethod}: ${queryip}:${queryport} : ${totalseconds}/${queryattempt}" fn_print_fail_eol_nl fn_script_log_warn "Querying port: ${querymethod}: ${queryip}:${queryport} : ${queryattempt} : FAIL" + fn_monitor_query_port_hint + fn_monitor_check_backup_update # Send alert if enabled. alert="monitor-query" alert.sh @@ -364,7 +490,7 @@ fn_monitor_query() { done # Second counter will wait for 15s before breaking loop. for seconds in {1..15}; do - fn_print_fail "Querying port: ${querymethod}: ${ip}:${queryport} : ${totalseconds}/${queryattempt}" + fn_print_fail "Querying port: ${querymethod}: ${queryip}:${queryport} : ${totalseconds}/${queryattempt}" fn_print_wait_eol fn_sleep_time_1 totalseconds=$((totalseconds + 1)) @@ -426,6 +552,8 @@ fn_monitor_check_starting fn_monitor_check_stopping fn_monitor_check_session fn_monitor_check_restart_request +fn_monitor_check_update_request +fn_monitor_check_backup_request # Monitor will not continue if session only check. if [ "${querymode}" != "1" ]; then diff --git a/lgsm/modules/command_postdetails.sh b/lgsm/modules/command_postdetails.sh index d029093b5f..b62834ffcb 100755 --- a/lgsm/modules/command_postdetails.sh +++ b/lgsm/modules/command_postdetails.sh @@ -58,11 +58,12 @@ else fi fn_print_dots "termbin.com" -link=$(cat "${postdetailslog}" | { - nc -w 10 termbin.com 9999 - echo $? > /tmp/nc_exit_status -} | tr -d '\n\0') -nc_exit_status=$(cat /tmp/nc_exit_status) +# Keep the upload status without sharing a temporary file between invocations. +link=$( + set -o pipefail + nc -w 10 termbin.com 9999 < "${postdetailslog}" | tr -d '\n\0' +) +nc_exit_status=$? if [ "${nc_exit_status}" -ne 0 ]; then fn_print_error_nl "Failed to post to termbin.com" fn_script_log_error "Failed to post to termbin.com" diff --git a/lgsm/modules/command_send.sh b/lgsm/modules/command_send.sh index 8b8a1a2525..f2197421a1 100755 --- a/lgsm/modules/command_send.sh +++ b/lgsm/modules/command_send.sh @@ -22,12 +22,20 @@ if [ "${status}" != "0" ]; then commandtosend="${userinput2}" else echo "" - commandtosend=$(fn_prompt_message "send: ") + if ! commandtosend=$(fn_prompt_message "send: "); then + echo -e "" + fn_print_error_nl "Unable to read a command to send: no input available" + fn_script_log_error "Unable to read a command to send: no input available" + # shellcheck disable=SC2034 # Used by core_exit.sh. + exitcode=2 + core_exit.sh + fi fi echo "" fn_print_dots "Sending command to console: \"${commandtosend}\"" fn_print_ok_nl "Sending command to console: \"${commandtosend}\"" - TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" "${commandtosend}" ENTER + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" -l "${commandtosend}" + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" ENTER fn_script_log_pass "Command \"${commandtosend}\" sent to console" else fn_print_error_nl "Unable to send command to console. Server not running" diff --git a/lgsm/modules/command_start.sh b/lgsm/modules/command_start.sh index 43b7a3858f..86bdf1c4e3 100755 --- a/lgsm/modules/command_start.sh +++ b/lgsm/modules/command_start.sh @@ -8,7 +8,8 @@ commandname="START" commandaction="Starting" moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" -addtimestamp="gawk '{ print strftime(\\\"[$logtimestampformat]\\\"), \\\$0 }'" +logtimestampformat_tmux="${logtimestampformat//%/%%}" +addtimestamp="gawk '{ print strftime(\"[$logtimestampformat_tmux]\"), \$0; fflush() }'" fn_firstcommand_set # This will allow the Jedi Knight 2 version to be printed in console on start. @@ -18,6 +19,74 @@ fn_start_jk2() { TERM=screen tmux -L "${socketname}" end -t "${sessionname}" version ENTER > /dev/null 2>&1 } +# Hytale: after the server boots, check whether it logged in. If it didn't (no saved login, or one that +# can't be decrypted, e.g. created on another machine or container), start the login, then show the +# login URL and send it as an alert, so it can be approved without opening the console. +# Prints the server console: the console log, or the tmux pane when console logging is off. +fn_start_hyt_console() { + if [ "${consolelogging}" == "off" ]; then + TERM=screen tmux -L "${socketname}" capture-pane -p -J -S - -t "${sessionname}" 2> /dev/null + else + cat "${consolelog}" 2> /dev/null + fi +} + +# Running With Rifles: the server starts in a lobby and runs a game mode once its start script is sent to the console. +fn_start_rwr_script() { + for _ in {1..120}; do + if fn_start_hyt_console | grep -a -q "Game loaded"; then + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" "start_script ${startscript} ${startpackage}" ENTER + fn_script_log_info "Sent start_script ${startscript} ${startpackage}" + sleep 5 + if fn_start_hyt_console | grep -a -q "script build failed"; then + fn_print_warn_nl "Running With Rifles could not start ${startpackage}/scripts/${startscript}. Check startpackage and startscript in ${configdirserver}" + fn_script_log_warn "Running With Rifles could not start ${startscript}" + fi + return + fi + sleep 1 + done + fn_print_warn_nl "Running With Rifles did not finish loading, the game mode was not started" + fn_script_log_warn "Running With Rifles did not finish loading, start_script ${startscript} was not sent" +} + +fn_start_hyt_login() { + hytloginurl="" + local hytloginsent="${hytloginpending}" + for _ in {1..120}; do + hytloginurl=$(fn_start_hyt_console | grep -a -oE "https://[^ ]*device/verify\?user_code=[A-Za-z0-9]+" | tail -1) + if [ -n "${hytloginurl}" ]; then + break + fi + # Logged in with the saved server login: nothing to do. + if fn_start_hyt_console | grep -a -q "Authentication successful"; then + fn_script_log_info "Hytale server login restored from saved credentials" + return + fi + # Booted without a usable login: ask the server to start one. + if [ "${hytloginsent}" != "1" ] && fn_start_hyt_console | grep -a -q "Hytale Server Booted" && fn_start_hyt_console | grep -a -q "No server tokens configured"; then + fn_script_log_info "Hytale server has no usable saved login, starting login" + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" "auth login device" ENTER + hytloginsent="1" + fi + sleep 1 + done + echo -e "" + if [ -n "${hytloginurl}" ]; then + echo -e "${bold}${lightyellow}Hytale server login required${default}" + echo -e "Open the URL below in a browser and log in with a Hytale account that owns the game." + echo -e "The code expires in 10 minutes. This is only needed once; the server saves the login." + echo -e "${hytloginurl}" + fn_script_log_info "Hytale server login required: ${hytloginurl}" + alert="hytale-login" + alert.sh + else + fn_print_warn_nl "Hytale server login required, but no login URL was found in the console yet" + echo -e "* Run ./${selfname} send \"/auth login device\" and approve the code shown in the console." + fn_script_log_warn "Hytale server login required, but no login URL was found in the console" + fi +} + fn_start_tmux() { # check for tmux size variables. if [[ "${servercfgtmuxwidth}" =~ ^[0-9]+$ ]]; then @@ -33,7 +102,7 @@ fn_start_tmux() { # Log rotation. fn_script_log_info "Rotating log files" - if [ "${engine}" == "unreal2" ] && [ -f "${gamelog}" ]; then + if [ -n "${gamelogdate}" ] && [ -f "${gamelog}" ]; then mv "${gamelog}" "${gamelogdate}" fi if [ -f "${lgsmlog}" ]; then @@ -48,6 +117,13 @@ fn_start_tmux() { fn_reload_startparameters + # Hytale: with no saved server login file, have the server start its login (OAuth device code) on boot. + # A saved login that can't be used is handled after boot by fn_start_hyt_login. + if [ "${shortname}" == "hyt" ] && [ ! -f "${systemdir}/auth.enc" ]; then + startparameters="${startparameters} --boot-command 'auth login device'" + hytloginpending="1" + fi + # Create uid to ensure unique tmux socket name. if [ ! -f "${datadir}/${selfname}.uid" ]; then check_status.sh @@ -82,7 +158,7 @@ fn_start_tmux() { if [ "${consolelogging}" == "on" ] || [ -z "${consolelogging}" ]; then # timestamp will break mcb update check. if [ "${logtimestamp}" == "on" ] && [ "${shortname}" != "mcb" ]; then - TERM=screen tmux -L "${socketname}" pipe-pane -o -t "${sessionname}" "exec bash -c \"cat | $addtimestamp\" >> '${consolelog}'" + TERM=screen tmux -L "${socketname}" pipe-pane -o -t "${sessionname}" "exec ${addtimestamp} >> '${consolelog}'" else TERM=screen tmux -L "${socketname}" pipe-pane -o -t "${sessionname}" "exec cat >> '${consolelog}'" fi @@ -160,6 +236,11 @@ fn_start_tmux() { alert="restarted" alert.sh fi + if [ "${shortname}" == "hyt" ]; then + fn_start_hyt_login + elif [ "${shortname}" == "rwr" ]; then + fn_start_rwr_script + fi fi rm -f "${lgsmlogdir:?}/.${selfname}-tmux-error.tmp" 2> /dev/null echo -en "\n" @@ -191,10 +272,17 @@ core_logs.sh # Will check for updates if updateonstart is yes. if [ "${updateonstart}" == "yes" ] || [ "${updateonstart}" == "1" ] || [ "${updateonstart}" == "on" ]; then - exitbypass=1 unset updateonstart - command_update.sh - fn_firstcommand_reset + if ! ( + unset exitbypass + command_update.sh + ); then + fn_print_warn_nl "Update failed, starting ${servername} anyway" + fn_script_log_warn "Update failed, starting ${servername} anyway" + fi + if [ "${shortname}" == "ahl" ]; then + fix_ahl.sh + fi fi fn_print_dots "${servername}" diff --git a/lgsm/modules/command_stop.sh b/lgsm/modules/command_stop.sh index 7bc4080650..3a7d1302fc 100755 --- a/lgsm/modules/command_stop.sh +++ b/lgsm/modules/command_stop.sh @@ -21,11 +21,193 @@ fn_stop_players_online() { fn_print_info_nl "${playersonline} players are on the server: stop prevented" fn_script_log_info "${playersonline} players are on the server: stop prevented" echo "${playersonline}" > "${lockdir:?}/${selfname}-player-numbers.lock" + # Monitor runs the update once the server is empty. + if [ "${firstcommandname}" == "UPDATE" ]; then + date '+%s' > "${lockdir:?}/${selfname}-update-request.lock" + if [ "${forceupdate}" == "1" ]; then + echo "force" >> "${lockdir:?}/${selfname}-update-request.lock" + fi + fn_print_info_nl "Update postponed until the server is empty" + fn_script_log_info "Update postponed until the server is empty" + elif [ "${firstcommandname}" == "BACKUP" ]; then + if [ ! -f "${lockdir}/${selfname}-backup-request.lock" ]; then + date '+%s' > "${lockdir:?}/${selfname}-backup-request.lock" + fi + fn_print_info_nl "Backup postponed until the server is empty" + fn_script_log_info "Backup postponed until the server is empty" + fi + fn_stop_cancel_locks + # Exit the whole command, including when called by another command (e.g. update) with exitbypass. + unset exitbypass core_exit.sh fi fi } +# Removes the lockfiles of the command that called stop when it ends without stopping the server. +fn_stop_cancel_locks() { + if [ "${firstcommandname}" == "UPDATE" ] || [ "${firstcommandname}" == "WORKSHOP-UPDATE" ]; then + rm -f "${lockdir:?}/update.lock" "${lockdir:?}/last-updated.lock" + elif [ "${firstcommandname}" == "VALIDATE" ]; then + rm -f "${lockdir:?}/update.lock" + elif [ "${firstcommandname}" == "BACKUP" ]; then + rm -f "${lockdir:?}/backup.lock" + fi +} + +# Tells players a warning countdown was cancelled, used when CTRL-C is pressed. +fn_stop_warn_players_cancel() { + if [ "$(cat "${lockdir}/${selfname}-warning.lock" 2> /dev/null)" == "$$" ]; then + fn_stop_warn_players_send "${warnplayersaction}" "0" + rm -f "${lockdir:?}/${selfname}-warning.lock" + fn_stop_cancel_locks + fi +} + +# Sets the game's chat command used to warn players, %s is replaced by the message. +fn_stop_warn_players_command() { + warncommand="" + if [ "${shortname}" == "pz" ]; then + warncommand='servermsg "%s"' + elif [ "${shortname}" == "dst" ]; then + warncommand='c_announce("%s")' + elif [ "${shortname}" == "scpsl" ]; then + warncommand="/bc 10 %s" + elif [ "${shortname}" == "vints" ]; then + warncommand="/announce %s" + elif [ "${shortname}" == "wmc" ]; then + warncommand="alert %s" + elif [ "${shortname}" == "av" ]; then + warncommand="/say %s" + elif [ "${shortname}" == "fctr" ]; then + warncommand="%s" + elif [ "${engine}" == "source" ] || [ "${engine}" == "source2" ] || [ "${engine}" == "goldsrc" ]; then + warncommand="say %s" + else + local saygames=(bt cod cod2 cod4 coduo codwaw ct etl hyt jk2 mc mcb mohaa mta nec pmc q2 q3 q4 ql qw rtcw rw sof2 terraria unt wet wf xnt) + local game + for game in "${saygames[@]}"; do + if [ "${shortname}" == "${game}" ]; then + warncommand="say %s" + fi + done + fi +} + +# Sends a warning message to players using the game's own chat command. +# A minutes value of 0 sends a cancelled message. +fn_stop_warn_players_send() { + local message="Server ${1} in ${2} minute" + if [ "${2}" != "1" ]; then + message+="s" + fi + if [ "${2}" == "0" ]; then + message="Server ${1} cancelled" + fi + local warnmessage="${warncommand//%s/${message}}" + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" -l "${warnmessage}" > /dev/null 2>&1 + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" ENTER > /dev/null 2>&1 +} + +# Waits for another LinuxGSM command that is already warning players on this server. +fn_stop_warn_players_wait() { + local warnlock="${lockdir}/${selfname}-warning.lock" + local warnpid + while [ -f "${warnlock}" ]; do + warnpid="$(cat "${warnlock}" 2> /dev/null)" + if [ -z "${warnpid}" ] || ! kill -0 "${warnpid}" 2> /dev/null; then + rm -f "${warnlock:?}" + break + fi + fn_print_info_nl "Warning players: another command is already warning players: waiting" + fn_script_log_info "Warning players: another command is already warning players: waiting" + sleep 30 + done +} + +# Counts down to the stop with in-game warnings, e.g. warnplayerstimer="15" warns at 15, 10, 5, 3 and 1 minutes. +# Skipped when the server is empty, and ends early if the server empties during the countdown. +fn_stop_warn_players() { + if [ "${firstcommandname}" == "STOP" ]; then + warnplayersaction="stopping" + elif [ "${firstcommandname}" == "RESTART" ] || [ "${firstcommandname}" == "BACKUP" ]; then + warnplayersaction="restarting" + elif [ "${firstcommandname}" == "UPDATE" ] || [ "${firstcommandname}" == "WORKSHOP-UPDATE" ]; then + warnplayersaction="updating" + else + return + fi + if [ -z "${warnplayerstimer}" ] || [ "${forceupdate}" == "1" ]; then + return + fi + if ! [[ "${warnplayerstimer}" =~ ^[0-9]+$ ]]; then + fn_print_warn_nl "Warning players: warnplayerstimer must be a number of minutes: skipped" + fn_script_log_warn "Warning players: warnplayerstimer \"${warnplayerstimer}\" is not a number of minutes: skipped" + return + fi + local timer="$((10#${warnplayerstimer}))" + if [ "${timer}" -eq 0 ]; then + return + fi + fn_stop_warn_players_command + if [ "${consoleinteract}" != "yes" ] || [ -z "${warncommand}" ]; then + fn_print_info_nl "Warning players: not supported by ${gamename}: skipped" + fn_script_log_info "Warning players: not supported by ${gamename}: skipped" + return + fi + + fn_stop_warn_players_wait + check_status.sh + if [ "${status}" == "0" ]; then + return + fi + + local steps=("${timer}") + local step + for step in 60 30 15 10 5 3 1; do + if [ "${step}" -lt "${timer}" ]; then + steps+=("${step}") + fi + done + + echo "$$" > "${lockdir:?}/${selfname}-warning.lock" + local i next + for i in "${!steps[@]}"; do + check_status.sh + if [ "${status}" == "0" ]; then + break + fi + # shellcheck disable=SC2034 # Used by check_players_online.sh. + playercheckforce=1 + check_players_online.sh + unset playercheckforce + if [ "${playerscounted}" == "1" ] && [ -z "${playersonline}" ]; then + fn_print_info_nl "Warning players: no players on the server" + fn_script_log_info "Warning players: no players on the server" + break + fi + if [ "${i}" == "0" ] && [ -n "${playercountunavailable}" ]; then + fn_print_info_nl "Warning players: unable to check for players (${playercountunavailable}): warning anyway" + fn_script_log_info "Warning players: unable to check for players (${playercountunavailable}): warning anyway" + fi + fn_stop_warn_players_send "${warnplayersaction}" "${steps[i]}" + fn_print_info_nl "Warning players: ${warnplayersaction} in ${steps[i]} minute(s)" + fn_script_log_info "Warning players: ${warnplayersaction} in ${steps[i]} minute(s)" + next="${steps[i + 1]:-0}" + local waitseconds=$(((steps[i] - next) * 60)) + while [ "${waitseconds}" -gt 0 ]; do + sleep 10 + waitseconds=$((waitseconds - 10)) + check_status.sh + if [ "${status}" == "0" ]; then + break 2 + fi + done + done + unset warnplayersaction + rm -f "${lockdir:?}/${selfname}-warning.lock" +} + # Attempts graceful shutdown by sending 'CTRL+c'. fn_stop_graceful_ctrlc() { fn_print_dots "Graceful: CTRL+c" @@ -110,196 +292,141 @@ fn_stop_graceful_goldsrc() { fi } -# telnet command for sdtd graceful shutdown. -fn_stop_graceful_sdtd_telnet() { - if [ -z "${telnetpassword}" ] || [ "${telnetpassword}" == "NOT SET" ]; then - sdtdtelnetshutdown=$(expect -c ' - proc abort {} { - puts "Timeout or EOF\n" - exit 1 - } - spawn telnet '"${telnetip}"' '"${telnetport}"' - expect { - "session." { send "shutdown\r" } - default abort - } - expect { eof } - puts "Completed.\n" - ') - else - sdtdtelnetshutdown=$(expect -c ' - proc abort {} { - puts "Timeout or EOF\n" - exit 1 - } - spawn telnet '"${telnetip}"' '"${telnetport}"' - expect { - "password:" { send "'"${telnetpassword}"'\r" } - default abort - } - expect { - "session." { send "shutdown\r" } - default abort - } - expect { eof } - puts "Completed.\n" - ') +# Opens a telnet connection using bash /dev/tcp. +# Usage: fn_stop_telnet_open "ip" +fn_stop_telnet_open() { + telnetoutput="" + exec {telnetfd}<> "/dev/tcp/${1}/${telnetport}" +} 2> /dev/null + +# Closes the telnet connection. +fn_stop_telnet_close() { + if [ -n "${telnetfd}" ]; then + exec {telnetfd}>&- + unset telnetfd fi } -# Attempts graceful shutdown of 7 Days To Die using telnet. -fn_stop_graceful_sdtd() { - fn_print_dots "Graceful: telnet" - fn_script_log_info "Graceful: telnet" - if [ "${telnetenabled}" == "false" ]; then - fn_print_info_nl "Graceful: telnet: DISABLED: Enable in ${servercfg}" - elif [ "$(command -v expect 2> /dev/null)" ]; then - # Tries to shutdown with both localhost and server IP. - for telnetip in 127.0.0.1 ${ip}; do - fn_print_dots "Graceful: telnet: ${telnetip}:${telnetport}" - fn_script_log_info "Graceful: telnet: ${telnetip}:${telnetport}" - fn_stop_graceful_sdtd_telnet - completed=$(echo -en "\n ${sdtdtelnetshutdown}" | grep "Completed.") - refused=$(echo -en "\n ${sdtdtelnetshutdown}" | grep "Timeout or EOF") - if [ "${refused}" ]; then - fn_print_error "Graceful: telnet: ${telnetip}:${telnetport} : " - fn_print_fail_eol_nl - fn_script_log_error "Graceful: telnet: ${telnetip}:${telnetport} : FAIL" - elif [ "${completed}" ]; then - break - fi - done +# Reads from the telnet connection until the text is received, ignoring case. +# Fails if the connection closes or nothing is received for the timeout. +# Usage: fn_stop_telnet_expect "text" "timeout_in_seconds" +fn_stop_telnet_expect() { + local char + while IFS= read -r -N 1 -t "${2:-10}" -u "${telnetfd}" char; do + telnetoutput+="${char}" + if [[ "${telnetoutput,,}" == *"${1,,}"* ]]; then + return 0 + fi + done + return 1 +} - # If telnet shutdown was successful will use telnet again to check - # the connection has closed, confirming that the tmux session can now be killed. - if [ "${completed}" ]; then - for seconds in {1..30}; do - fn_stop_graceful_sdtd_telnet - refused=$(echo -en "\n ${sdtdtelnetshutdown}" | grep "Timeout or EOF") - if [ "${refused}" ]; then - fn_print_ok "Graceful: telnet: ${telnetip}:${telnetport} : " - fn_print_ok_eol_nl - fn_script_log_pass "Graceful: telnet: ${telnetip}:${telnetport} : ${seconds} seconds" - if [ "${statusalert}" == "on" ] && [ "${firstcommandname}" == "STOP" ]; then - alert="stopped" - alert.sh - fi - break - fi - fn_sleep_time_1 - fn_print_dots "Graceful: telnet: ${seconds}" - done - # If telnet shutdown fails tmux shutdown will be used, this risks loss of world save. - else - if [ "${refused}" ]; then - fn_print_error "Graceful: telnet: " - fn_print_fail_eol_nl - fn_script_log_error "Graceful: telnet: ${telnetip}:${telnetport} : FAIL" - else - fn_print_error_nl "Graceful: telnet: Unknown error" - fn_script_log_error "Graceful: telnet: Unknown error" - fi - echo -en "\n" | tee -a "${lgsmlog}" - echo -en "Telnet output:" | tee -a "${lgsmlog}" - echo -en "\n ${sdtdtelnetshutdown}" | tee -a "${lgsmlog}" - echo -en "\n\n" | tee -a "${lgsmlog}" +# Reads from the telnet connection until the server closes it. +fn_stop_telnet_read_to_close() { + local char + while IFS= read -r -N 1 -t 10 -u "${telnetfd}" char; do + telnetoutput+="${char}" + done +} + +# Sends a line to the telnet connection. +# Usage: fn_stop_telnet_send "text" +fn_stop_telnet_send() { + (printf '%s\r\n' "${1}" >&"${telnetfd}") 2> /dev/null +} + +# Telnet session for 7 Days to Die graceful shutdown. +# Usage: fn_stop_graceful_sdtd_telnet "ip" +fn_stop_graceful_sdtd_telnet() { + fn_stop_telnet_open "${1}" || return 1 + if [ -n "${telnetpassword}" ] && [ "${telnetpassword}" != "NOT SET" ]; then + if ! fn_stop_telnet_expect "password:" || ! fn_stop_telnet_send "${telnetpassword}"; then + fn_stop_telnet_close + return 1 fi - else - fn_print_warn "Graceful: telnet: expect not installed: " - fn_print_fail_eol_nl - fn_script_log_warn "Graceful: telnet: expect not installed: FAIL" fi + if fn_stop_telnet_expect "session." && fn_stop_telnet_send "shutdown"; then + fn_stop_telnet_read_to_close + fn_stop_telnet_close + return 0 + fi + fn_stop_telnet_close + return 1 } -# Attempts graceful shutdown of Soulmask using telnet. -fn_stop_graceful_sm() { +# Telnet session for Soulmask graceful shutdown. +# Usage: fn_stop_graceful_sm_telnet "ip" +fn_stop_graceful_sm_telnet() { + fn_stop_telnet_open "${1}" || return 1 + if fn_stop_telnet_send "saveworld 1" && fn_stop_telnet_expect "world is saved" 120 && fn_stop_telnet_send "quit 1"; then + fn_stop_telnet_read_to_close + fn_stop_telnet_close + return 0 + fi + fn_stop_telnet_close + return 1 +} + +# Attempts graceful shutdown using a telnet session. +# Tries localhost first, then the telnet and server IPs. +# Usage: fn_stop_graceful_telnet "session_function" "timeout_in_seconds" +# e.g.: fn_stop_graceful_telnet "fn_stop_graceful_sdtd_telnet" "60" +fn_stop_graceful_telnet() { fn_print_dots "Graceful: telnet" fn_script_log_info "Graceful: telnet" if [ "${telnetenabled}" == "false" ]; then fn_print_info_nl "Graceful: telnet: DISABLED: Enable in ${servercfg}" - elif [ "$(command -v expect 2> /dev/null)" ]; then - # Tries to shutdown with both localhost and server IP. - for telnetip in 127.0.0.1 ${ip}; do - fn_print_dots "Graceful: telnet: ${telnetip}:${telnetport}" - fn_script_log_info "Graceful: telnet: ${telnetip}:${telnetport}" - fn_stop_graceful_sm_telnet - completed=$(echo -en "\n ${smtelnetshutdown}" | grep "Completed.") - refused=$(echo -en "\n ${smtelnetshutdown}" | grep "Timeout or EOF") - if [ "${refused}" ]; then - fn_print_error "Graceful: telnet: ${telnetip}:${telnetport} : " - fn_print_fail_eol_nl - fn_script_log_error "Graceful: telnet: ${telnetip}:${telnetport} : FAIL" - elif [ "${completed}" ]; then - break - fi - done - - # If telnet shutdown was successful will use telnet again to check - # the connection has closed, confirming that the tmux session can now be killed. - if [ "${completed}" ]; then - for seconds in {1..30}; do - fn_stop_graceful_sm_telnet - refused=$(echo -en "\n ${smtelnetshutdown}" | grep "Timeout or EOF") - if [ "${refused}" ]; then - fn_print_ok "Graceful: telnet: ${telnetip}:${telnetport} : " - fn_print_ok_eol_nl - fn_script_log_pass "Graceful: telnet: ${telnetip}:${telnetport} : ${seconds} seconds" - if [ "${statusalert}" == "on" ] && [ "${firstcommandname}" == "STOP" ]; then - alert="stopped" - alert.sh - fi - break - fi - fn_sleep_time_1 - fn_print_dots "Graceful: telnet: ${seconds}" - done - # If telnet shutdown fails, show it and stop - else - if [ "${refused}" ]; then - fn_print_error "Graceful: telnet: " - fn_print_fail_eol_nl - fn_script_log_error "Graceful: telnet: ${telnetip}:${telnetport} : FAIL" - else - fn_print_error_nl "Graceful: telnet: Unknown error" - fn_script_log_error "Graceful: telnet: Unknown error" + fn_script_log_info "Graceful: telnet: DISABLED" + return + fi + local telnetaddresses=("127.0.0.1") + local telnetaddress telnetsent + for telnetaddress in "${telnetip[@]}" ${ip}; do + if [ -n "${telnetaddress}" ] && [[ " ${telnetaddresses[*]} " != *" ${telnetaddress} "* ]]; then + telnetaddresses+=("${telnetaddress}") + fi + done + for telnetaddress in "${telnetaddresses[@]}"; do + fn_print_dots "Graceful: telnet: ${telnetaddress}:${telnetport}" + fn_script_log_info "Graceful: telnet: ${telnetaddress}:${telnetport}" + if "${1}" "${telnetaddress}"; then + telnetsent=1 + break + fi + fn_print_error "Graceful: telnet: ${telnetaddress}:${telnetport}: " + fn_print_fail_eol_nl + fn_script_log_error "Graceful: telnet: ${telnetaddress}:${telnetport}: FAIL" + if [ -n "${telnetoutput}" ]; then + fn_script_log_error "Graceful: telnet: output: ${telnetoutput//$'\r'/}" + fi + done + if [ -z "${telnetsent}" ]; then + return + fi + # Waits up to ${seconds} seconds giving the server time to shutdown gracefully. + for ((seconds = 1; seconds <= ${2}; seconds++)); do + check_status.sh + if [ "${status}" == "0" ]; then + fn_print_ok "Graceful: telnet: ${telnetaddress}:${telnetport}: ${seconds}" + fn_print_ok_eol_nl + fn_script_log_pass "Graceful: telnet: ${telnetaddress}:${telnetport}: OK: ${seconds} seconds" + if [ "${statusalert}" == "on" ] && [ "${firstcommandname}" == "STOP" ]; then + alert="stopped" + alert.sh fi - echo -en "\n" | tee -a "${lgsmlog}" - echo -en "Telnet output:" | tee -a "${lgsmlog}" - echo -en "\n ${smtelnetshutdown}" | tee -a "${lgsmlog}" - echo -en "\n\n" | tee -a "${lgsmlog}" + break fi - else - fn_print_warn "Graceful: telnet: expect not installed: " + fn_sleep_time_1 + fn_print_dots "Graceful: telnet: ${telnetaddress}:${telnetport}: ${seconds}" + done + check_status.sh + if [ "${status}" != "0" ]; then + fn_print_error "Graceful: telnet: ${telnetaddress}:${telnetport}: " fn_print_fail_eol_nl - fn_script_log_warn "Graceful: telnet: expect not installed: FAIL" + fn_script_log_error "Graceful: telnet: ${telnetaddress}:${telnetport}: FAIL" fi } -# telnet command for soulmask graceful shutdown. -fn_stop_graceful_sm_telnet() { - smtelnetshutdown=$(expect -c ' - proc abort {} { - puts "Timeout or EOF\n" - exit 1 - } - spawn telnet '"${telnetip}"' '"${telnetport}"' - expect { - "Hello:" { send "saveworld 1\r" } - default abort - } - expect { - "the world is saved." { send "quit 1\r" } - default abort - } - expect { - "World is closing..." {} - default abort - } - expect { eof } - puts "Completed.\n" - ') -} - # Attempts graceful shutdown by sending /save /stop. fn_stop_graceful_avorion() { fn_print_dots "Graceful: /save /stop" @@ -333,6 +460,58 @@ fn_stop_graceful_avorion() { fi } +fn_stop_graceful_rwr() { + fn_print_dots "Graceful: save_profiles stop_server" + fn_script_log_info "Graceful: save_profiles stop_server" + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" save_profiles ENTER > /dev/null 2>&1 + fn_sleep_time_5 + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" stop_server ENTER > /dev/null 2>&1 + fn_sleep_time_5 + fn_stop_graceful_ctrlc +} + +fn_stop_graceful_ce() { + fn_print_dots "Graceful: CTRL+c" + fn_script_log_info "Graceful: CTRL+c" + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" C-c > /dev/null 2>&1 + fn_sleep_time_5 + fn_stop_graceful_ctrlc +} + +# Attempts graceful shutdown of Rising World using 'shutdown'. +# Its console can miss input, so the command is sent again every 10 seconds until the server stops. +fn_stop_graceful_rw() { + fn_print_dots "Graceful: sending \"shutdown\"" + fn_script_log_info "Graceful: sending \"shutdown\"" + for ((seconds = 1; seconds <= 120; seconds++)); do + if [ $((seconds % 10)) -eq 1 ]; then + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" ENTER > /dev/null 2>&1 + sleep 1 + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" -l "shutdown" > /dev/null 2>&1 + TERM=screen tmux -L "${socketname}" send-keys -t "${sessionname}" ENTER > /dev/null 2>&1 + fi + check_status.sh + if [ "${status}" == "0" ]; then + fn_print_ok "Graceful: sending \"shutdown\": ${seconds}" + fn_print_ok_eol_nl + fn_script_log_pass "Graceful: sending \"shutdown\": OK: ${seconds} seconds" + if [ "${statusalert}" == "on" ] && [ "${firstcommandname}" == "STOP" ]; then + alert="stopped" + alert.sh + fi + break + fi + fn_sleep_time_1 + fn_print_dots "Graceful: sending \"shutdown\": ${seconds}" + done + check_status.sh + if [ "${status}" != "0" ]; then + fn_print_error "Graceful: sending \"shutdown\": " + fn_print_fail_eol_nl + fn_script_log_error "Graceful: sending \"shutdown\": FAIL" + fi +} + fn_stop_graceful_select() { if [ "${stopmode}" == "1" ]; then fn_stop_tmux @@ -349,7 +528,7 @@ fn_stop_graceful_select() { elif [ "${stopmode}" == "7" ]; then fn_stop_graceful_cmd "exit" 30 elif [ "${stopmode}" == "8" ]; then - fn_stop_graceful_sdtd + fn_stop_graceful_telnet "fn_stop_graceful_sdtd_telnet" "60" elif [ "${stopmode}" == "9" ]; then fn_stop_graceful_goldsrc elif [ "${stopmode}" == "10" ]; then @@ -359,7 +538,13 @@ fn_stop_graceful_select() { elif [ "${stopmode}" == "12" ]; then fn_stop_graceful_cmd "shutdown" 30 elif [ "${stopmode}" == "13" ]; then - fn_stop_graceful_sm + fn_stop_graceful_telnet "fn_stop_graceful_sm_telnet" "30" + elif [ "${stopmode}" == "14" ]; then + fn_stop_graceful_rwr + elif [ "${stopmode}" == "15" ]; then + fn_stop_graceful_rw + elif [ "${stopmode}" == "16" ]; then + fn_stop_graceful_ce fi } @@ -389,7 +574,6 @@ fn_stop_pre_check() { fn_print_skip_nl "${servername} is already stopped" fn_script_log_info "${servername} is already stopped" else - fn_stop_players_online # Select graceful shutdown. fn_stop_graceful_select # Check status again, a kill tmux session if graceful shutdown failed. @@ -402,13 +586,21 @@ fn_stop_pre_check() { fn_print_dots "" check.sh +info_game.sh + +# Players are checked and warned before the stopping lockfile is created, +# as a warning countdown can outlast monitor's stale lockfile check. +if [ "${status}" != "0" ]; then + fn_stop_players_online + fn_stop_warn_players + check_status.sh +fi # Create a stopping lockfile that only exists while the stop command is running. date '+%s' > "${lockdir:?}/${selfname}-stopping.lock" fn_print_dots "${servername}" -info_game.sh fn_stop_pre_check # Remove started lockfile. diff --git a/lgsm/modules/command_update.sh b/lgsm/modules/command_update.sh index a7cfc1b127..5d7b364ff3 100755 --- a/lgsm/modules/command_update.sh +++ b/lgsm/modules/command_update.sh @@ -10,9 +10,50 @@ commandaction="Updating" moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_firstcommand_set +fn_update_apply() { + check_status.sh + updatestatus="${status}" + if [ "${updatestatus}" != "0" ]; then + fn_print_restart_warning + exitbypass=1 + command_stop.sh + fn_firstcommand_reset + fi + ( + unset exitbypass + "$@" + exit 0 + ) + updateexitcode=$? + if [ "${updateexitcode}" -eq 0 ]; then + date +%s > "${lockdir:?}/last-updated.lock" + fi + if [ "${updatestatus}" != "0" ]; then + # shellcheck disable=SC2034 # Used by command_start.sh. + exitbypass=1 + command_start.sh + fn_firstcommand_reset + fi + unset exitbypass + if [ "${updateexitcode}" -ne 0 ]; then + rm -f "${lockdir:?}/update.lock" + # shellcheck disable=SC2034 # Used by alert.sh. + alert="update-failed" + alert.sh + # shellcheck disable=SC2034 # Used by core_exit.sh. + exitcode="${updateexitcode}" + core_exit.sh + fi +} + fn_print_dots "" check.sh core_logs.sh +check_update_lock.sh + +# A postponed update is requested again if players are still online. +rm -f "${lockdir:?}/${selfname}-update-request.lock" + check_last_update.sh if [ "${shortname}" == "ts3" ]; then @@ -25,24 +66,43 @@ elif [ "${shortname}" == "pmc" ] || [ "${shortname}" == "vpmc" ] || [ "${shortna update_pmc.sh elif [ "${shortname}" == "fctr" ]; then update_fctr.sh +elif [ "${shortname}" == "fivem" ]; then + update_fivem.sh +elif [ "${shortname}" == "hyt" ]; then + update_hyt.sh elif [ "${shortname}" == "mta" ]; then update_mta.sh elif [ "${shortname}" == "jk2" ]; then update_jk2.sh +elif [ "${shortname}" == "jk3" ]; then + update_jk3.sh +elif [ "${shortname}" == "luanti" ]; then + update_luanti.sh +elif [ "${shortname}" == "orar" ]; then + update_openra.sh elif [ "${shortname}" == "vints" ]; then update_vints.sh +elif [ "${shortname}" == "bfe" ]; then + update_bfe.sh elif [ "${shortname}" == "bb" ]; then update_bb.sh elif [ "${shortname}" == "ut99" ]; then update_ut99.sh elif [ "${shortname}" == "xnt" ]; then update_xnt.sh +elif [ "${shortname}" == "qw" ]; then + update_qw.sh elif [ "${shortname}" == "etl" ]; then update_etl.sh else update_steamcmd.sh fi +if { [ "${shortname}" == "arma3" ] || [ "${shortname}" == "dayz" ] || [ "${shortname}" == "bt" ] || [ "${shortname}" == "col" ] || [ "${shortname}" == "hw" ] || [ "${shortname}" == "l4d2" ] || [ "${shortname}" == "ohd" ] || [ "${shortname}" == "sb" ] || [ "${shortname}" == "squad" ] || [ "${shortname}" == "squad44" ] || [ "${shortname}" == "sol" ] || [ "${shortname}" == "st" ]; } && { [ -n "${workshopmods}" ] || [ -f "${datadir}/${selfname}-workshop.txt" ]; }; then + workshop_core.sh + fn_workshop_update +fi + # remove update lockfile. rm -f "${lockdir:?}/update.lock" diff --git a/lgsm/modules/command_update_linuxgsm.sh b/lgsm/modules/command_update_linuxgsm.sh index 80ff74cfb9..0d4d0ab911 100755 --- a/lgsm/modules/command_update_linuxgsm.sh +++ b/lgsm/modules/command_update_linuxgsm.sh @@ -90,7 +90,8 @@ if [ "${script_diff}" != "" ]; then if [ ! -d "${backupdir}/script" ]; then mkdir -p "${backupdir}/script" fi - cp "${rootdir}/${selfname}" "${backupdir}/script/${selfname}-$(date +"%m_%d_%Y_%M").bak" + scriptbackup="${backupdir}/script/${selfname}-$(date +"%m_%d_%Y_%M").bak" + cp "${rootdir}/${selfname}" "${scriptbackup}" exitcode=$? if [ "${exitcode}" -ne 0 ]; then fn_print_fail_eol_nl @@ -98,25 +99,45 @@ if [ "${script_diff}" != "" ]; then core_exit.sh else fn_print_ok_eol_nl - fn_script_log_pass "Backup script${selfname}" - echo -e "backup location [ ${backupdir}/script/${selfname}-$(date +"%m_%d_%Y_%M").bak ]" - fn_script_log_pass "Backup location ${backupdir}/script/${selfname}-$(date +"%m_%d_%Y_%M").bak" + fn_script_log_pass "Backup script ${selfname}" + echo -e "backup location [ ${scriptbackup} ]" + fn_script_log_pass "Backup location ${scriptbackup}" fi echo -en "copying ${selfname}" fn_script_log_info "Copying ${selfname}" - cp "${tmpdir}/linuxgsm.sh" "${rootdir}/${selfname}" - sed -i "s+shortname=\"core\"+shortname=\"${shortname}\"+g" "${rootdir}/${selfname}" - sed -i "s+gameservername=\"core\"+gameservername=\"${gameservername}\"+g" "${rootdir}/${selfname}" - sed -i "s+gamename=\"core\"+gamename=\"${gamename}\"+g" "${rootdir}/${selfname}" - sed -i "s+githubuser=\"GameServerManagers\"+githubuser=\"${githubuser}\"+g" "${rootdir}/${selfname}" - sed -i "s+githubrepo=\"LinuxGSM\"+githubrepo=\"${githubrepo}\"+g" "${rootdir}/${selfname}" - sed -i "s+githubbranch=\"master\"+githubbranch=\"${githubbranch}\"+g" "${rootdir}/${selfname}" + cp "${tmpdir}/linuxgsm.sh" "${tmpdir}/${selfname}.update" \ + && sed -i \ + -e "s+shortname=\"core\"+shortname=\"${shortname}\"+g" \ + -e "s+gameservername=\"core\"+gameservername=\"${gameservername}\"+g" \ + -e "s+gamename=\"core\"+gamename=\"${gamename}\"+g" \ + -e "s+githubuser=\"GameServerManagers\"+githubuser=\"${githubuser}\"+g" \ + -e "s+githubrepo=\"LinuxGSM\"+githubrepo=\"${githubrepo}\"+g" \ + -e "s+githubbranch=\"master\"+githubbranch=\"${githubbranch}\"+g" \ + "${tmpdir}/${selfname}.update" + exitcode=$? + if [ "${exitcode}" -ne 0 ]; then + fn_print_fail_eol_nl + fn_script_log_fail "Preparing ${selfname} in ${tmpdir}" + rm -f "${tmpdir:?}/${selfname}.update" + core_exit.sh + fi + cp "${tmpdir}/${selfname}.update" "${rootdir}/${selfname}" exitcode=$? + rm -f "${tmpdir:?}/${selfname}.update" if [ "${exitcode}" -ne 0 ]; then fn_print_fail_eol_nl fn_script_log_fail "copying ${selfname}" + echo -en "restoring ${selfname} from backup\c" + fn_script_log_info "Restoring ${selfname} from ${scriptbackup}" + if cp "${scriptbackup}" "${rootdir}/${selfname}"; then + fn_print_ok_eol_nl + fn_script_log_pass "Restoring ${selfname} from backup" + else + fn_print_fail_eol_nl + fn_script_log_fail "Restoring ${selfname} from backup ${scriptbackup}" + fi core_exit.sh else fn_print_ok_eol_nl diff --git a/lgsm/modules/command_validate.sh b/lgsm/modules/command_validate.sh index 30c20e96ea..ff24c84688 100755 --- a/lgsm/modules/command_validate.sh +++ b/lgsm/modules/command_validate.sh @@ -30,6 +30,7 @@ fn_validate() { fn_print_dots "" check.sh core_logs.sh +check_update_lock.sh fn_print_dots "SteamCMD" diff --git a/lgsm/modules/command_workshop_update.sh b/lgsm/modules/command_workshop_update.sh new file mode 100755 index 0000000000..9d39185222 --- /dev/null +++ b/lgsm/modules/command_workshop_update.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# LinuxGSM command_workshop_update.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Downloads, updates and removes Steam Workshop mods set in workshopmods. + +commandname="WORKSHOP-UPDATE" +commandaction="Updating Workshop Mods" +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" +fn_firstcommand_set + +fn_print_dots "" +check.sh +core_logs.sh +check_update_lock.sh + +if [ -z "${workshopmods}" ] && [ ! -f "${datadir}/${selfname}-workshop.txt" ]; then + fn_print_info_nl "No Workshop mods set. Add Workshop IDs to workshopmods in ${configdirserver}" + fn_script_log_info "No Workshop mods set" + core_exit.sh +fi + +workshop_core.sh +fn_workshop_update + +rm -f "${lockdir:?}/update.lock" + +core_exit.sh diff --git a/lgsm/modules/core_dl.sh b/lgsm/modules/core_dl.sh index c3194a915d..8e3dcfb638 100755 --- a/lgsm/modules/core_dl.sh +++ b/lgsm/modules/core_dl.sh @@ -19,6 +19,20 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" +# Removes consecutive duplicate lines from SteamCMD output without buffering. +fn_dl_steamcmd_output() { + local line="" + local previousline="" + local firstline="1" + while IFS= read -r line || [ -n "${line}" ]; do + if [ -n "${firstline}" ] || [ "${line}" != "${previousline}" ]; then + printf '%s\n' "${line}" + fi + previousline="${line}" + firstline="" + done +} + fn_dl_steamcmd() { remotelocation="SteamCMD" fn_print_start_nl "${remotelocation}" @@ -61,23 +75,25 @@ fn_dl_steamcmd() { # To do error checking for SteamCMD the output of steamcmd will be saved to a log. steamcmdlog="${lgsmlogdir}/${selfname}-steamcmd.log" - # clear previous steamcmd log - if [ -f "${steamcmdlog}" ]; then - rm -f "${steamcmdlog:?}" - fi + local invalidplatformworkaround="" counter=0 while [ "${counter}" -eq 0 ] || [ "${exitcode}" -ne 0 ]; do counter=$((counter + 1)) + # clear previous steamcmd log + rm -f "${steamcmdlog:?}" # Select SteamCMD parameters # If GoldSrc (appid 90) servers. GoldSrc (appid 90) require extra commands. if [ "${appid}" == "90" ]; then # If using a specific branch. if [ -n "${branch}" ] && [ -n "${betapassword}" ]; then - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_set_config 90 mod "${appidmod}" +app_update "${appid}" -beta "${branch}" -betapassword "${betapassword}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_set_config 90 mod "${appidmod}" +app_update "${appid}" -beta "${branch}" -betapassword "${betapassword}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + exitcode="${PIPESTATUS[0]}" elif [ -n "${branch}" ]; then - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_set_config 90 mod "${appidmod}" +app_update "${appid}" -beta "${branch}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_set_config 90 mod "${appidmod}" +app_update "${appid}" -beta "${branch}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + exitcode="${PIPESTATUS[0]}" else - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_set_config 90 mod "${appidmod}" +app_update "${appid}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_set_config 90 mod "${appidmod}" +app_update "${appid}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + exitcode="${PIPESTATUS[0]}" fi # Force Windows Platform type. elif [ "${steamcmdforcewindows}" == "yes" ]; then @@ -88,18 +104,20 @@ fn_dl_steamcmd() { fn_script_log_fail "${commandaction} ${selfname}: baseappid is set but supportdir is not defined" core_exit.sh fi - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +@sSteamCmdForcePlatformType windows +force_install_dir "${supportdir}" +login "${steamuser}" "${steampass}" +app_update "${baseappid}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +@sSteamCmdForcePlatformType windows +force_install_dir "${supportdir}" +login "${steamuser}" "${steampass}" +app_update "${baseappid}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" exitcode="${PIPESTATUS[0]}" - if [ "${exitcode}" -ne 0 ]; then - continue - fi fi - if [ -n "${branch}" ] && [ -n "${betapassword}" ]; then - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" -betapassword "${betapassword}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" - elif [ -n "${branch}" ]; then - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" - else - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" + if [ -z "${baseappid}" ] || [ "${exitcode}" -eq 0 ]; then + if [ -n "${branch}" ] && [ -n "${betapassword}" ]; then + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" -betapassword "${betapassword}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + exitcode="${PIPESTATUS[0]}" + elif [ -n "${branch}" ]; then + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + exitcode="${PIPESTATUS[0]}" + else + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + exitcode="${PIPESTATUS[0]}" + fi fi # All other servers. else @@ -110,25 +128,25 @@ fn_dl_steamcmd() { fn_script_log_fail "${commandaction} ${selfname}: baseappid is set but supportdir is not defined" core_exit.sh fi - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${supportdir}" +login "${steamuser}" "${steampass}" +app_update "${baseappid}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${supportdir}" +login "${steamuser}" "${steampass}" +app_update "${baseappid}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" exitcode="${PIPESTATUS[0]}" - if [ "${exitcode}" -ne 0 ]; then - continue - fi fi - if [ -n "${branch}" ] && [ -n "${betapassword}" ]; then - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" -betapassword "${betapassword}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" - elif [ -n "${branch}" ]; then - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" - else - "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" "${validateparam[@]}" +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" + if [ -z "${baseappid}" ] || [ "${exitcode}" -eq 0 ]; then + if [ -n "${branch}" ] && [ -n "${betapassword}" ]; then + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" -betapassword "${betapassword}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + exitcode="${PIPESTATUS[0]}" + elif [ -n "${branch}" ]; then + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + exitcode="${PIPESTATUS[0]}" + else + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" "${validateparam[@]}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + exitcode="${PIPESTATUS[0]}" + fi fi fi # Error checking for SteamCMD. Some errors will loop to try again and some will just exit. - # Check also if we have more errors than retries to be sure that we do not loop to many times and error out. - exitcode=$? - if [ -n "$(grep -i "Error!" "${steamcmdlog}" | tail -1)" ] && [ "$(grep -ic "Error!" "${steamcmdlog}")" -ge "${counter}" ]; then + if grep -qi "Error!" "${steamcmdlog}"; then # Not enough space. if [ -n "$(grep "0x202" "${steamcmdlog}" | tail -1)" ]; then fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: Not enough disk space to download server files" @@ -139,7 +157,16 @@ fn_dl_steamcmd() { fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: Not enough disk space to download server files" fn_script_log_fail "${commandaction} ${selfname}: ${remotelocation}: Not enough disk space to download server files" core_exit.sh - # Invalid platform for app/update request. + # Invalid platform (SteamCMD bug, e.g. Left 4 Dead 2): retry once after a Windows platform download. + elif [ -n "$(grep -i "Invalid platform" "${steamcmdlog}" | tail -1)" ] && [ "${steamcmdforcewindows}" != "yes" ] && [ -z "${invalidplatformworkaround}" ]; then + invalidplatformworkaround="1" + fn_print_error2_nl "${commandaction} ${selfname}: ${remotelocation}: Invalid platform - applying SteamCMD Windows platform workaround" + fn_script_log_error "${commandaction} ${selfname}: ${remotelocation}: Invalid platform - applying SteamCMD Windows platform workaround" + "${unbuffercommand[@]}" "${steamcmdcommandarray[@]}" +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" +quit | fn_dl_steamcmd_output | tee -a "${lgsmlog}" "${steamcmdlog}" + validateparam=("validate") + rm -f "${steamcmdlog:?}" + counter=0 + # Invalid platform for app/update request (after the workaround, or when forcing Windows). elif [ -n "$(grep -i "Invalid platform" "${steamcmdlog}" | tail -1)" ]; then fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: Invalid platform for AppID ${appid}" fn_print_nl "Check steamcmdforcewindows setting and system architecture (x86_64 required for most servers)" @@ -175,6 +202,11 @@ fn_dl_steamcmd() { elif [ -n "$(grep "0x6A6" "${steamcmdlog}" | tail -1)" ]; then fn_print_error2_nl "${commandaction} ${selfname}: ${remotelocation}: Corrupt update files" fn_script_log_error "${commandaction} ${selfname}: ${remotelocation}: Corrupt update files" + # Steam app metadata unavailable. + elif [ -n "$(grep -i "Missing configuration" "${steamcmdlog}" | tail -1)" ]; then + fn_print_error2_nl "${commandaction} ${selfname}: ${remotelocation}: Missing configuration - Steam app metadata unavailable for AppID ${appid}" + fn_print_nl "Please provide content log to LinuxGSM developers https://linuxgsm.com/steamcmd-error" + fn_script_log_error "${commandaction} ${selfname}: ${remotelocation}: Missing configuration - Steam app metadata unavailable for AppID ${appid}" else fn_print_error2_nl "${commandaction} ${selfname}: ${remotelocation}: Unknown error occurred" fn_print_nl "Please provide content log to LinuxGSM developers https://linuxgsm.com/steamcmd-error" @@ -256,7 +288,7 @@ fn_dl_hash() { fi } -# Extracts bzip2, gzip or zip files. +# Extracts gzip, bzip2, xz or zip files. Any other file type fails. # Extracts can be defined in code like so: # fn_dl_extract "${local_filedir}" "${local_filename}" "${extractdest}" "${extractsrc}" # fn_dl_extract "/home/gameserver/lgsm/tmp" "file.tar.bz2" "/home/gamserver/serverfiles" @@ -277,37 +309,44 @@ fn_dl_extract() { fn_script_log_fail "Extracting ${local_filename}" fn_script_log_fail "File ${local_filedir}/${local_filename} not found" core_exit.sh + return 1 fi mime=$(file -b --mime-type "${local_filedir}/${local_filename}") if [ "${mime}" == "application/gzip" ] || [ "${mime}" == "application/x-gzip" ]; then if [ -n "${extractsrc}" ]; then - extractcmd=$(tar -zxf "${local_filedir}/${local_filename}" -C "${extractdest}" --strip-components=1 "${extractsrc}") + extractcmd=$(tar -zxf "${local_filedir}/${local_filename}" -C "${extractdest}" --strip-components=1 "${extractsrc}" 2>&1) else - extractcmd=$(tar -zxf "${local_filedir}/${local_filename}" -C "${extractdest}") + extractcmd=$(tar -zxf "${local_filedir}/${local_filename}" -C "${extractdest}" 2>&1) fi elif [ "${mime}" == "application/x-bzip2" ]; then if [ -n "${extractsrc}" ]; then - extractcmd=$(tar -jxf "${local_filedir}/${local_filename}" -C "${extractdest}" --strip-components=1 "${extractsrc}") + extractcmd=$(tar -jxf "${local_filedir}/${local_filename}" -C "${extractdest}" --strip-components=1 "${extractsrc}" 2>&1) else - extractcmd=$(tar -jxf "${local_filedir}/${local_filename}" -C "${extractdest}") + extractcmd=$(tar -jxf "${local_filedir}/${local_filename}" -C "${extractdest}" 2>&1) fi elif [ "${mime}" == "application/x-xz" ]; then if [ -n "${extractsrc}" ]; then - extractcmd=$(tar -Jxf "${local_filedir}/${local_filename}" -C "${extractdest}" --strip-components=1 "${extractsrc}") + extractcmd=$(tar -Jxf "${local_filedir}/${local_filename}" -C "${extractdest}" --strip-components=1 "${extractsrc}" 2>&1) else - extractcmd=$(tar -Jxf "${local_filedir}/${local_filename}" -C "${extractdest}") + extractcmd=$(tar -Jxf "${local_filedir}/${local_filename}" -C "${extractdest}" 2>&1) fi elif [ "${mime}" == "application/zip" ]; then if [ -n "${extractsrc}" ]; then temp_extractdir="${tmpdir}/${extractsrc}" - extractcmd=$(unzip -qo "${local_filedir}/${local_filename}" "${extractsrc}/*" -d "${temp_extractdir}") - cp -a "${temp_extractdir}/${extractsrc}/." "${extractdest}/" - rm -rf "${temp_extractdir}" + extractcmd=$(unzip -qo "${local_filedir}/${local_filename}" "${extractsrc}/*" -d "${temp_extractdir}" 2>&1 && cp -a "${temp_extractdir}/${extractsrc}/." "${extractdest}/" 2>&1) else - extractcmd=$(unzip -qo -d "${extractdest}" "${local_filedir}/${local_filename}") + extractcmd=$(unzip -qo -d "${extractdest}" "${local_filedir}/${local_filename}" 2>&1) fi + else + extractcmd="Unsupported archive type: ${mime}" + false fi exitcode=$? + # Clean up after capturing the exit code so cleanup cannot mask a failed extraction or copy. + if [ -n "${temp_extractdir}" ]; then + rm -rf "${temp_extractdir}" + unset temp_extractdir + fi if [ "${exitcode}" -ne 0 ]; then fn_print_fail_eol_nl fn_script_log_fail "Extracting ${local_filename}" @@ -316,6 +355,7 @@ fn_dl_extract() { fi echo -e "${extractcmd}" core_exit.sh + return 1 else fn_print_ok_eol_nl fn_script_log_pass "Extracting ${local_filename}" @@ -332,6 +372,9 @@ fn_fetch_trap() { echo -en "downloading ${local_filename}" fn_print_removed_eol_nl fn_script_log_info "Downloading ${local_filename}...REMOVED" + if [ "${local_filename}" == "core_exit.sh" ]; then + exit 130 + fi core_exit.sh } @@ -369,25 +412,29 @@ fn_check_file() { if [ "${exitcode}" -ne 0 ]; then if [ ${counter} -ge 2 ]; then fn_print_fail_eol_nl + checkflag=1 if [ -f "${lgsmlog}" ]; then fn_script_log_fail "Checking ${remote_filename}" fn_script_log_fail "${fileurl}" - checkflag=1 fi else fn_print_error_eol_nl + checkflag=2 if [ -f "${lgsmlog}" ]; then fn_script_log_error "Checking ${remote_filename}" fn_script_log_error "${fileurl}" - checkflag=2 fi fi else - fn_print_ok_eol - echo -en "\033[2K\\r" + if [ -n "${plainoutput}" ]; then + fn_print_ok_eol_nl + else + fn_print_ok_eol + echo -en "\033[2K\\r" + fi + checkflag=0 if [ -f "${lgsmlog}" ]; then fn_script_log_pass "Checking ${remote_filename}" - checkflag=0 fi break fi @@ -442,16 +489,24 @@ fn_fetch_file() { fi # Trap will remove part downloaded files if canceled. trap fn_fetch_trap INT - curlcmd=(curl --connect-timeout 3 --fail -L -o "${local_filedir}/${local_filename}" --retry 2 -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.${randomint}.212 Safari/537.36") + curlcmd=(curl --connect-timeout 10 --fail -L -o "${local_filedir}/${local_filename}" --retry 2 -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.${randomint}.212 Safari/537.36") + if [[ "${fileurl}" == https://* ]]; then + curlcmd+=(--proto-redir "=https") + fi # if is large file show progress, else be silent local exitcode="" large_files=("bz2" "gz" "zip" "jar" "xz") if grep -qE "(^|\s)${local_filename##*.}(\s|$)" <<< "${large_files[@]}"; then - echo -e "downloading file [ ${italic}${local_filename}${default} ]" - fn_sleep_time - "${curlcmd[@]}" --progress-bar "${fileurl}" 2>&1 - exitcode=$? + if [ -n "${plainoutput}" ]; then + "${curlcmd[@]}" --silent --show-error "${fileurl}" 2>&1 + exitcode=$? + else + echo -e "downloading file [ ${italic}${local_filename}${default} ]" + fn_sleep_time + "${curlcmd[@]}" --progress-bar "${fileurl}" 2>&1 + exitcode=$? + fi echo -en "downloading file [ ${italic}${local_filename}${default} ]" else echo -en "fetching ${fileurl_name} [ ${italic}${local_filename}${default} ]\c" @@ -475,6 +530,9 @@ fn_fetch_file() { fn_script_log_fail "Downloading ${local_filename}..." fn_script_log_fail "${fileurl}" fi + if [ "${local_filename}" == "core_exit.sh" ]; then + exit 1 + fi core_exit.sh else fn_print_error_eol_nl diff --git a/lgsm/modules/core_exit.sh b/lgsm/modules/core_exit.sh index 1dd6e2f460..9e92a1a3c1 100755 --- a/lgsm/modules/core_exit.sh +++ b/lgsm/modules/core_exit.sh @@ -19,12 +19,18 @@ fn_exit_dev_debug() { fi } +fn_print_plain_flush + # If running dependency check as root will remove any files that belong to root user. if [ "$(whoami)" == "root" ]; then find "${lgsmdir}"/ -group root -prune -exec rm -rf {} + > /dev/null 2>&1 find "${logdir}"/ -group root -prune -exec rm -rf {} + > /dev/null 2>&1 fi +if [ -z "${exitbypass}" ] && [ "${updatelocklevel}" == "${BASH_SUBSHELL}" ] && [ "$(cat "${lockdir}/updating.lock" 2> /dev/null)" == "$$" ]; then + rm -f "${lockdir:?}/updating.lock" +fi + if [ "${exitbypass}" ]; then unset exitbypass elif [ "${exitcode}" -ne 0 ]; then diff --git a/lgsm/modules/core_getopt.sh b/lgsm/modules/core_getopt.sh index ad09bf1df5..57cda74c75 100755 --- a/lgsm/modules/core_getopt.sh +++ b/lgsm/modules/core_getopt.sh @@ -37,6 +37,8 @@ cmd_validate=("v;validate" "command_validate.sh" "Validate server files with Ste cmd_mods_install=("mi;mods-install" "command_mods_install.sh" "View and install available mods/addons.") cmd_mods_remove=("mr;mods-remove" "command_mods_remove.sh" "View and remove an installed mod/addon.") cmd_mods_update=("mu;mods-update" "command_mods_update.sh" "Update installed mods/addons.") +# Server with Steam Workshop downloads. +cmd_workshop_update=("wu;workshop-update" "command_workshop_update.sh" "Install and update Steam Workshop mods.") # Server specific. cmd_change_password=("pw;change-password" "command_ts3_server_pass.sh" "Change TS3 serveradmin password.") cmd_install_default_resources=("ir;install-default-resources" "command_install_resources_mta.sh" "Install the MTA default resources.") @@ -66,11 +68,11 @@ currentopt=("${cmd_start[@]}" "${cmd_stop[@]}" "${cmd_restart[@]}" "${cmd_monito currentopt+=("${cmd_update_linuxgsm[@]}") # Exclude noupdate games here. -if [ "${shortname}" == "jk2" ] || [ "${shortname}" == "etl" ] || [ "${engine}" != "idtech3" ]; then - if [ "${shortname}" != "bf1942" ] && [ "${shortname}" != "bfv" ] && [ "${engine}" != "idtech2" ] && [ "${engine}" != "iw2.0" ] && [ "${engine}" != "iw3.0" ] && [ "${engine}" != "quake" ] && [ "${shortname}" != "samp" ] && [ "${shortname}" != "ut2k4" ]; then +if [ "${shortname}" == "jk2" ] || [ "${shortname}" == "jk3" ] || [ "${shortname}" == "etl" ] || [ "${engine}" != "idtech3" ]; then + if [ "${querytype}" != "protocol-valve-won" ] && [ "${shortname}" != "bf1942" ] && [ "${shortname}" != "bfv" ] && [ "${engine}" != "idtech2" ] && [ "${engine}" != "iw2.0" ] && [ "${engine}" != "iw3.0" ] && { [ "${engine}" != "quake" ] || [ "${shortname}" == "qw" ]; } && [ "${shortname}" != "samp" ] && [ "${shortname}" != "ut2k4" ]; then currentopt+=("${cmd_update[@]}" "${cmd_check_update[@]}") - # force update for SteamCMD or Multi Theft Auto only. - if [ "${appid}" ] || [ "${shortname}" == "mta" ]; then + # force update for SteamCMD, Multi Theft Auto, Hytale or FiveM only. + if [ "${appid}" ] || [ "${shortname}" == "mta" ] || [ "${shortname}" == "hyt" ] || [ "${shortname}" == "fivem" ]; then currentopt+=("${cmd_force_update[@]}") fi fi @@ -95,7 +97,7 @@ fi ## Game server exclusive commands. # FastDL command. -if [ "${engine}" == "source" ] || [ "${engine}" == "goldsrc" ]; then +if { [ "${engine}" == "source" ] || [ "${engine}" == "goldsrc" ]; } && [ "${querytype}" != "protocol-valve-won" ]; then currentopt+=("${cmd_fastdl[@]}") fi @@ -137,10 +139,15 @@ if [ "${shortname}" == "squad" ]; then fi ## Mods commands. -if [ "${engine}" == "source" ] || [ "${shortname}" == "rust" ] || [ "${shortname}" == "hq" ] || [ "${shortname}" == "sdtd" ] || [ "${shortname}" == "cs" ] || [ "${shortname}" == "dod" ] || [ "${shortname}" == "tfc" ] || [ "${shortname}" == "ns" ] || [ "${shortname}" == "ts" ] || [ "${shortname}" == "hldm" ] || [ "${shortname}" == "vh" ]; then +if [ "${engine}" == "source" ] || [ "${shortname}" == "cs2" ] || [ "${shortname}" == "rust" ] || [ "${shortname}" == "hq" ] || [ "${shortname}" == "sdtd" ] || [ "${shortname}" == "cs" ] || [ "${shortname}" == "dod" ] || [ "${shortname}" == "tfc" ] || [ "${shortname}" == "ns" ] || [ "${shortname}" == "ts" ] || [ "${shortname}" == "hldm" ] || [ "${shortname}" == "vh" ]; then currentopt+=("${cmd_mods_install[@]}" "${cmd_mods_remove[@]}" "${cmd_mods_update[@]}") fi +## Workshop commands. +if [ "${shortname}" == "arma3" ] || [ "${shortname}" == "dayz" ] || [ "${shortname}" == "bt" ] || [ "${shortname}" == "col" ] || [ "${shortname}" == "hw" ] || [ "${shortname}" == "l4d2" ] || [ "${shortname}" == "ohd" ] || [ "${shortname}" == "sb" ] || [ "${shortname}" == "squad" ] || [ "${shortname}" == "squad44" ] || [ "${shortname}" == "sol" ] || [ "${shortname}" == "st" ]; then + currentopt+=("${cmd_workshop_update[@]}") +fi + ## Installer. currentopt+=("${cmd_install[@]}" "${cmd_auto_install[@]}") diff --git a/lgsm/modules/core_logs.sh b/lgsm/modules/core_logs.sh index 7b435b563b..6d8ed5a117 100755 --- a/lgsm/modules/core_logs.sh +++ b/lgsm/modules/core_logs.sh @@ -58,6 +58,11 @@ if [ "$(find "${lgsmlogdir}"/ -type f -mtime +"${logdays}" | wc -l)" -ne "0" ]; find "${gamelogdir}"/ -type f -mtime +"${logdays}" | tee >> "${lgsmlog}" gamecount=$(find "${gamelogdir}"/ -type f -mtime +"${logdays}" | wc -l) find "${gamelogdir}"/ -mtime +"${logdays}" -type f -exec rm -f {} \; + # Rotated game logfiles. + elif [ -n "${gamelogdate}" ] && [ -d "${gamelogdir}" ]; then + find "${gamelogdir}"/ -maxdepth 1 -type f -name "${selfname}-game-*.log" -mtime +"${logdays}" | tee >> "${lgsmlog}" + gamecount=$(find "${gamelogdir}"/ -maxdepth 1 -type f -name "${selfname}-game-*.log" -mtime +"${logdays}" | wc -l) + find "${gamelogdir}"/ -maxdepth 1 -type f -name "${selfname}-game-*.log" -mtime +"${logdays}" -exec rm -f {} \; fi # Console logfiles. if [ "${consolelog}" ]; then diff --git a/lgsm/modules/core_messages.sh b/lgsm/modules/core_messages.sh index da5fd43e37..447eb4d0d5 100755 --- a/lgsm/modules/core_messages.sh +++ b/lgsm/modules/core_messages.sh @@ -10,9 +10,16 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" # nl: new line: message is following by a new line. # eol: end of line: message is placed at the end of the current line. fn_ansi_loader() { + # plain: stdout is not a terminal, output complete lines with no terminal control sequences. + unset plainoutput plainpending + if [ ! -t 1 ]; then + plainoutput="1" + fi # carriage return. creeol="\r" - if [ "${ansi}" != "off" ]; then + if [ -n "${plainoutput}" ]; then + creeol="" + elif [ "${ansi}" != "off" ]; then # echo colors default="\e[0m" black="\e[30m" @@ -33,15 +40,21 @@ fn_ansi_loader() { white="\e[97m" # erase to end of line. creeol+="\033[K" + # text styles + bold="\e[1m" + dim="\e[2m" + italic="\e[3m" + underline="\e[4m" + reverse="\e[7m" fi - # carriage return & erase to end of line. - creeol="\r\033[K" +} - bold="\e[1m" - dim="\e[2m" - italic="\e[3m" - underline="\e[4m" - reverse="\e[7m" +# plain: print any held in-place message as its own line. +fn_print_plain_flush() { + if [ -n "${plainpending}" ]; then + echo -e "${plainpending}" + unset plainpending + fi } fn_sleep_time() { @@ -110,22 +123,31 @@ fn_script_log_info() { ################################## fn_print() { + fn_print_plain_flush echo -en "$*${default}" } fn_print_nl() { + fn_print_plain_flush echo -e "$*${default}" } # Helper function to print messages with a specific format and color +# plain: in-place messages are held until replaced, completed by an eol message or flushed. fn_print_message() { local type="$1" local color="$2" local message="$3" + local line if [ "${commandaction}" ]; then - echo -en "${bold}${creeol}[${color} ${type} ${default}]${default} ${commandaction} ${selfname}: ${message}${default}" + line="[${color} ${type} ${default}]${default} ${commandaction} ${selfname}: ${message}${default}" + else + line="[${color} ${type} ${default}]${default} ${message}${default}" + fi + if [ -n "${plainoutput}" ]; then + plainpending="${line}" else - echo -en "${bold}${cree}[${color} ${type} ${default}]${default} ${message}${default}" + echo -en "${bold}${creeol}${line}" fi fn_sleep_time } @@ -134,6 +156,7 @@ fn_print_message_nl() { local type="$1" local color="$2" local message="$3" + unset plainpending if [ "${commandaction}" ]; then echo -e "${bold}${creeol}[${color} ${type} ${default}]${default} ${commandaction} ${selfname}: ${message}${default}" else @@ -142,6 +165,28 @@ fn_print_message_nl() { fn_sleep_time } +# Helper function to print eol messages with a specific color +fn_print_eol() { + local type="$1" + local color="$2" + if [ -n "${plainpending}" ]; then + plainpending+=" ... ${type}" + else + echo -en " ... ${color}${type}${default}" + fi +} + +fn_print_eol_nl() { + local type="$1" + local color="$2" + if [ -n "${plainpending}" ]; then + echo -e "${plainpending} ... ${type}" + unset plainpending + else + echo -e " ... ${color}${type}${default}" + fi +} + # [ .... ] fn_print_dots() { fn_print_message "...." "${default}" "$*" @@ -222,7 +267,9 @@ fn_print_start_nl() { # Separator is different for details. fn_messages_separator() { if [ "${commandname}" == "DETAILS" ]; then - printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' = + # Fall back to 80 columns when there is no terminal (e.g. cron or Docker); bash 5.3+ rejects an empty printf width. + local columns="${COLUMNS:-$(tput cols 2> /dev/null)}" + printf '%*s\n' "${columns:-80}" '' | tr ' ' = else echo -e "${bold}=================================${default}" fn_sleep_time @@ -232,6 +279,7 @@ fn_messages_separator() { # No More Room in Hell Debug # ================================= fn_print_header() { + fn_print_plain_flush echo -e "" echo -e "${bold}${lightyellow}${gamename} ${commandaction}${default}" fn_messages_separator @@ -305,6 +353,7 @@ fn_print_skip2_nl() { # Y/N Prompt fn_prompt_yn() { + fn_print_plain_flush echo -e "" local prompt="$1" local initial="$2" @@ -318,7 +367,14 @@ fn_prompt_yn() { fi while true; do - read -e -i "${initial}" -p "${prompt}" -r yn + if ! read -e -i "${initial}" -p "${prompt}" -r yn && [ -z "${yn}" ]; then + echo -e "" + fn_print_error_nl "Unable to read an answer: no input available" + fn_script_log_error "Unable to read an answer to \"${1}\": no input available" + # shellcheck disable=SC2034 # Used by core_exit.sh. + exitcode=2 + core_exit.sh + fi case "${yn}" in [Yy] | [Yy][Ee][Ss]) return 0 ;; [Nn] | [Nn][Oo]) return 1 ;; @@ -332,7 +388,9 @@ fn_prompt_message() { while true; do unset prompt local prompt="$1" - read -e -p "${prompt}" -r answer + if ! read -e -p "${prompt}" -r answer && [ -z "${answer}" ]; then + return 1 + fi if fn_prompt_yn "Continue" Y; then break fi @@ -345,166 +403,166 @@ fn_prompt_message() { # YES fn_print_yes_eol() { - echo -en " ... ${cyan}YES${default}" + fn_print_eol "YES" "${cyan}" fn_sleep_time } fn_print_yes_eol_nl() { - echo -e " ... ${cyan}YES${default}" + fn_print_eol_nl "YES" "${cyan}" fn_sleep_time } # NO fn_print_no_eol() { - echo -en " ... ${red}NO${default}" + fn_print_eol "NO" "${red}" fn_sleep_time } fn_print_no_eol_nl() { - echo -e " ... ${red}NO${default}" + fn_print_eol_nl "NO" "${red}" fn_sleep_time } # OK fn_print_ok_eol() { - echo -en " ... ${green}OK${default}" + fn_print_eol "OK" "${green}" fn_sleep_time } fn_print_ok_eol_nl() { - echo -e " ... ${green}OK${default}" + fn_print_eol_nl "OK" "${green}" fn_sleep_time } # FAIL fn_print_fail_eol() { - echo -en " ... ${red}FAIL${default}" + fn_print_eol "FAIL" "${red}" fn_sleep_time } fn_print_fail_eol_nl() { - echo -e " ... ${red}FAIL${default}" + fn_print_eol_nl "FAIL" "${red}" fn_sleep_time } # ERROR fn_print_error_eol() { - echo -en " ... ${red}ERROR${default}" + fn_print_eol "ERROR" "${red}" fn_sleep_time } fn_print_error_eol_nl() { - echo -e " ... ${red}ERROR${default}" + fn_print_eol_nl "ERROR" "${red}" fn_sleep_time } # WAIT fn_print_wait_eol() { - echo -en " ... ${cyan}WAIT${default}" + fn_print_eol "WAIT" "${cyan}" fn_sleep_time } fn_print_wait_eol_nl() { - echo -e " ... ${cyan}WAIT${default}" + fn_print_eol_nl "WAIT" "${cyan}" fn_sleep_time } # WARN fn_print_warn_eol() { - echo -en " ... ${lightyellow}WARN${default}" + fn_print_eol "WARN" "${lightyellow}" fn_sleep_time } fn_print_warn_eol_nl() { - echo -e " ... ${lightyellow}WARN${default}" + fn_print_eol_nl "WARN" "${lightyellow}" fn_sleep_time } # INFO fn_print_info_eol() { - echo -en " ... ${cyan}INFO${default}" + fn_print_eol "INFO" "${cyan}" fn_sleep_time } fn_print_info_eol_nl() { - echo -e " ... ${cyan}INFO${default}" + fn_print_eol_nl "INFO" "${cyan}" fn_sleep_time } # QUERYING fn_print_querying_eol() { - echo -en " ... ${cyan}QUERYING${default}" + fn_print_eol "QUERYING" "${cyan}" fn_sleep_time_1 } fn_print_querying_eol_nl() { - echo -e " ... ${cyan}QUERYING${default}" + fn_print_eol_nl "QUERYING" "${cyan}" fn_sleep_time_1 } # CHECKING fn_print_checking_eol() { - echo -en " ... ${cyan}CHECKING${default}" + fn_print_eol "CHECKING" "${cyan}" fn_sleep_time_1 } fn_print_checking_eol_nl() { - echo -e " ... ${cyan}CHECKING${default}" + fn_print_eol_nl "CHECKING" "${cyan}" fn_sleep_time_1 } # DELAY fn_print_delay_eol() { - echo -en " ... ${green}DELAY${default}" + fn_print_eol "DELAY" "${green}" fn_sleep_time_1 } fn_print_delay_eol_nl() { - echo -e " ... ${green}DELAY${default}" + fn_print_eol_nl "DELAY" "${green}" fn_sleep_time_1 } # CANCELED fn_print_canceled_eol() { - echo -en " ... ${lightyellow}CANCELED${default}" + fn_print_eol "CANCELED" "${lightyellow}" fn_sleep_time_1 } fn_print_canceled_eol_nl() { - echo -e " ... ${lightyellow}CANCELED${default}" + fn_print_eol_nl "CANCELED" "${lightyellow}" fn_sleep_time_1 } # REMOVED fn_print_removed_eol() { - echo -en " ... ${red}REMOVED${default}" + fn_print_eol "REMOVED" "${red}" fn_sleep_time_1 } fn_print_removed_eol_nl() { - echo -e " ... ${red}REMOVED${default}" + fn_print_eol_nl "REMOVED" "${red}" fn_sleep_time_1 } # UPDATE fn_print_update_eol() { - echo -en " ... ${lightblue}UPDATE${default}" + fn_print_eol "UPDATE" "${lightblue}" fn_sleep_time } fn_print_update_eol_nl() { - echo -e " ... ${lightblue}UPDATE${default}" + fn_print_eol_nl "UPDATE" "${lightblue}" fn_sleep_time } # SKIP fn_print_skip_eol() { - echo -en " ... ${cyan}SKIP${default}" + fn_print_eol "SKIP" "${cyan}" fn_sleep_time } fn_print_skip_eol_nl() { - echo -e " ... ${cyan}SKIP${default}" + fn_print_eol_nl "SKIP" "${cyan}" fn_sleep_time } diff --git a/lgsm/modules/core_modules.sh b/lgsm/modules/core_modules.sh index 9d72f5ce7c..47add40e40 100755 --- a/lgsm/modules/core_modules.sh +++ b/lgsm/modules/core_modules.sh @@ -8,7 +8,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" -modulesversion="v26.2.0" +modulesversion="v26.5.0" # Core @@ -181,6 +181,16 @@ command_wipe.sh() { fn_fetch_module } +command_workshop_update.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + +install_fivem_license.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + install_squad_license.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -268,6 +278,11 @@ check_tmuxception.sh() { fn_fetch_module } +check_update_lock.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + check_version.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -292,6 +307,13 @@ mods_list.sh() { fn_fetch_module } +# Workshop + +workshop_core.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + # Dev command_dev_clear_modules.sh() { @@ -346,6 +368,11 @@ fix.sh() { fn_fetch_module } +fix_ahl.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_ark.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -366,6 +393,16 @@ fix_av.sh() { fn_fetch_module } +fix_bf1942.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + +fix_bfv.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_bo.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -381,16 +418,51 @@ fix_cmw.sh() { fn_fetch_module } +fix_cod.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + +fix_cod2.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + +fix_coduo.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + +fix_codwaw.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_csgo.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module } +fix_cswon.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + +fix_ct.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_dst.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module } +fix_hlwon.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_hw.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -401,6 +473,11 @@ fix_ins.sh() { fn_fetch_module } +fix_ios.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_kf.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -416,11 +493,21 @@ fix_mcb.sh() { fn_fetch_module } +fix_mohaa.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_mta.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module } +fix_nd.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_nmrih.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -501,6 +588,11 @@ fix_tf2.sh() { fn_fetch_module } +fix_ts.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_ts3.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -526,11 +618,21 @@ fix_ut3.sh() { fn_fetch_module } +fix_ut99.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_vh.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module } +fix_vs.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + fix_wurm.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -680,11 +782,26 @@ update_fctr.sh() { fn_fetch_module } +update_fivem.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + +update_hyt.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + update_jk2.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module } +update_jk3.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + update_mc.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -700,11 +817,21 @@ update_mta.sh() { fn_fetch_module } +update_openra.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + update_pmc.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module } +update_qw.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + update_steamcmd.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module @@ -720,11 +847,21 @@ update_ut99.sh() { fn_fetch_module } +update_bfe.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + update_bb.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module } +update_luanti.sh() { + modulefile="${FUNCNAME[0]}" + fn_fetch_module +} + update_vints.sh() { modulefile="${FUNCNAME[0]}" fn_fetch_module diff --git a/lgsm/modules/core_steamcmd.sh b/lgsm/modules/core_steamcmd.sh index 463a1f7dac..d8043ed269 100755 --- a/lgsm/modules/core_steamcmd.sh +++ b/lgsm/modules/core_steamcmd.sh @@ -14,8 +14,8 @@ fn_install_steamcmd() { if [ ! -d "${steamcmddir}" ]; then mkdir -p "${steamcmddir}" fi - fn_fetch_file "http://media.steampowered.com/client/steamcmd_linux.tar.gz" "" "" "" "${tmpdir}" "steamcmd_linux.tar.gz" "nochmodx" "norun" "noforce" "nohash" - fn_dl_extract "${tmpdir}" "steamcmd_linux.tar.gz" "${steamcmddir}" + fn_fetch_file "https://media.steampowered.com/client/steamcmd_linux.tar.gz" "" "" "" "${tmpdir}" "steamcmd_linux.tar.gz" "nochmodx" "norun" "noforce" "nohash" + fn_dl_extract "${tmpdir}" "steamcmd_linux.tar.gz" "${steamcmddir}" || return 1 chmod +x "${steamcmddir}/steamcmd.sh" } @@ -239,25 +239,8 @@ fn_update_steamcmd_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_dl_steamcmd - # If server started. - else - fn_print_restart_warning - exitbypass=1 - command_stop.sh - fn_firstcommand_reset - exitbypass=1 - fn_dl_steamcmd - exitbypass=1 - command_start.sh - fn_firstcommand_reset - fi - unset exitbypass + fn_update_apply fn_dl_steamcmd alert="update" elif [ "${commandname}" == "CHECK-UPDATE" ]; then alert="check-update" diff --git a/lgsm/modules/core_trap.sh b/lgsm/modules/core_trap.sh index f9ff17ff16..c17a5894cd 100755 --- a/lgsm/modules/core_trap.sh +++ b/lgsm/modules/core_trap.sh @@ -17,6 +17,11 @@ fn_exit_trap() { if [ -z "${exitcode}" ]; then exitcode=0 fi + if [ "$(type -t fn_stop_warn_players_cancel)" == "function" ]; then + fn_stop_warn_players_cancel + fi + # CTRL-C exits LinuxGSM, including while one command is running another (e.g. restart running stop). + unset exitbypass core_exit.sh } diff --git a/lgsm/modules/fix.sh b/lgsm/modules/fix.sh index f31030779c..ea74c7228f 100755 --- a/lgsm/modules/fix.sh +++ b/lgsm/modules/fix.sh @@ -53,8 +53,8 @@ fn_apply_fix() { fi } -apply_pre_start_fix=(arma3 armar ark av bt bo csgo cmw dst hw ins kf nmrih onset pvr ro rust rw samp sdtd sfc sm sof2 squad st tf2 terraria ts3 mcb mta unt vh wurm xnt zmr) -apply_post_install_fix=(av kf kf2 ro ut2k4 ut ut3) +apply_pre_start_fix=(ahl arma3 armar ark av bf1942 bfv bt bo csgo cmw cod cod2 coduo codwaw cswon ct dst hlwon hw ins ios kf nd nmrih onset pvr ro rust rw samp sdtd sfc sm sof2 squad st tf2 terraria ts ts3 mcb mohaa mta unt ut ut99 vh vs wurm xnt zmr) +apply_post_install_fix=(av kf kf2 nd ro ut2k4 ut3) # validate registered fixes for safe development for fix in "${apply_pre_start_fix[@]}" "${apply_post_install_fix[@]}"; do diff --git a/lgsm/modules/fix_ahl.sh b/lgsm/modules/fix_ahl.sh new file mode 100755 index 0000000000..a547d64a25 --- /dev/null +++ b/lgsm/modules/fix_ahl.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# LinuxGSM fix_ahl.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Action Half-Life. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export GLIBC_TUNABLES="${GLIBC_TUNABLES:+${GLIBC_TUNABLES}:}glibc.rtld.execstack=2" + +rehldsversion="3.15.0.896" +rehldsfile="rehlds-bin-${rehldsversion}.zip" + +if ! grep -qs '"BetaKey"[[:space:]]*"steam_legacy"' "${serverfiles}/steamapps/appmanifest_90.acf"; then + fn_print_warn_nl "ReHLDS requires the steam_legacy branch: run ./${selfname} force-update" + fn_script_log_warn "ReHLDS requires the steam_legacy branch: run ./${selfname} force-update" +elif [ "$(md5sum "${serverfiles}/engine_i486.so" 2> /dev/null | awk '{print $1}')" != "a3aa351c97922f17b8290dce3f5b9bf0" ]; then + # shellcheck disable=SC2034 # Used by fn_fix_msg_start_nl and fn_fix_msg_end. + fixname="ReHLDS ${rehldsversion}" + fn_fix_msg_start_nl + fn_fetch_file "https://github.com/rehlds/ReHLDS/releases/download/${rehldsversion}/${rehldsfile}" "" "" "" "${tmpdir}" "${rehldsfile}" "nochmodx" "norun" "noforce" "87b8dd8bce18ccc2295069f7382bb4d3" + fn_dl_extract "${tmpdir}" "${rehldsfile}" "${tmpdir}/rehlds" + cp -a "${tmpdir}/rehlds/bin/linux32/." "${serverfiles}/" + chmod +x "${serverfiles}/hlds_linux" "${serverfiles}/hltv" + fn_clear_tmp + fn_fix_msg_end +fi diff --git a/lgsm/modules/fix_bf1942.sh b/lgsm/modules/fix_bf1942.sh new file mode 100755 index 0000000000..bce71f39e2 --- /dev/null +++ b/lgsm/modules/fix_bf1942.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# LinuxGSM fix_bf1942.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Battlefield 1942. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}" + +if ldd "${executabledir}/bf1942_lnxded.static" 2>&1 | grep -qE "lib(ncurses|tinfo)\.so\.5 => not found"; then + # shellcheck disable=SC2034 # Used by fn_fix_msg_start_nl and fn_fix_msg_end. + fixname="libncurses5 i386" + fn_fix_msg_start_nl + fn_fetch_file "https://linuxgsm.download/libraries/libncurses5-i386-6.3-2ubuntu0.3-linuxgsm-20261102.tar.xz" "" "" "" "${tmpdir}" "libncurses5-i386-6.3-2ubuntu0.3-linuxgsm-20261102.tar.xz" "nochmodx" "norun" "noforce" "dd1cc98dd60420ea14345deb6a6beb8a" + fn_dl_extract "${tmpdir}" "libncurses5-i386-6.3-2ubuntu0.3-linuxgsm-20261102.tar.xz" "${serverfiles}" + fn_clear_tmp + fn_fix_msg_end +fi diff --git a/lgsm/modules/fix_bfv.sh b/lgsm/modules/fix_bfv.sh new file mode 100755 index 0000000000..142d7062e1 --- /dev/null +++ b/lgsm/modules/fix_bfv.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# LinuxGSM fix_bfv.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Battlefield: Vietnam. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}" + +if ldd "${executabledir}/bfv_linded.static" 2>&1 | grep -qE "lib(ncurses|tinfo)\.so\.5 => not found"; then + # shellcheck disable=SC2034 # Used by fn_fix_msg_start_nl and fn_fix_msg_end. + fixname="libncurses5 i386" + fn_fix_msg_start_nl + fn_fetch_file "https://linuxgsm.download/libraries/libncurses5-i386-6.3-2ubuntu0.3-linuxgsm-20261102.tar.xz" "" "" "" "${tmpdir}" "libncurses5-i386-6.3-2ubuntu0.3-linuxgsm-20261102.tar.xz" "nochmodx" "norun" "noforce" "dd1cc98dd60420ea14345deb6a6beb8a" + fn_dl_extract "${tmpdir}" "libncurses5-i386-6.3-2ubuntu0.3-linuxgsm-20261102.tar.xz" "${serverfiles}" + fn_clear_tmp + fn_fix_msg_end +fi diff --git a/lgsm/modules/fix_cod.sh b/lgsm/modules/fix_cod.sh new file mode 100755 index 0000000000..d103ac857d --- /dev/null +++ b/lgsm/modules/fix_cod.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# LinuxGSM fix_cod.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Call of Duty. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}" + +if ldd "${executabledir}/cod_lnxded" 2>&1 | grep -q "libstdc++\.so\.5 => not found"; then + # shellcheck disable=SC2034 # Used by fn_fix_msg_start_nl and fn_fix_msg_end. + fixname="libstdc++5 i386" + fn_fix_msg_start_nl + fn_fetch_file "https://linuxgsm.download/libraries/libstdc++5-i386-3.3.6-34.tar.xz" "" "" "" "${tmpdir}" "libstdc++5-i386-3.3.6-34.tar.xz" "nochmodx" "norun" "noforce" "288a4cc9d6b7647f28c702028437e0f3" + fn_dl_extract "${tmpdir}" "libstdc++5-i386-3.3.6-34.tar.xz" "${serverfiles}" + fn_clear_tmp + fn_fix_msg_end +fi diff --git a/lgsm/modules/fix_cod2.sh b/lgsm/modules/fix_cod2.sh new file mode 100755 index 0000000000..60d43d4db3 --- /dev/null +++ b/lgsm/modules/fix_cod2.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# LinuxGSM fix_cod2.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Call of Duty 2. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}" +export GLIBC_TUNABLES="${GLIBC_TUNABLES:+${GLIBC_TUNABLES}:}glibc.rtld.execstack=2" + +if ldd "${executabledir}/cod2_lnxded" 2>&1 | grep -q "libstdc++\.so\.5 => not found"; then + # shellcheck disable=SC2034 # Used by fn_fix_msg_start_nl and fn_fix_msg_end. + fixname="libstdc++5 i386" + fn_fix_msg_start_nl + fn_fetch_file "https://linuxgsm.download/libraries/libstdc++5-i386-3.3.6-34.tar.xz" "" "" "" "${tmpdir}" "libstdc++5-i386-3.3.6-34.tar.xz" "nochmodx" "norun" "noforce" "288a4cc9d6b7647f28c702028437e0f3" + fn_dl_extract "${tmpdir}" "libstdc++5-i386-3.3.6-34.tar.xz" "${serverfiles}" + fn_clear_tmp + fn_fix_msg_end +fi diff --git a/lgsm/modules/fix_coduo.sh b/lgsm/modules/fix_coduo.sh new file mode 100755 index 0000000000..a2f87b75d8 --- /dev/null +++ b/lgsm/modules/fix_coduo.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# LinuxGSM fix_coduo.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Call of Duty: United Offensive. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}" + +if ldd "${executabledir}/coduo_lnxded" 2>&1 | grep -q "libstdc++\.so\.5 => not found"; then + # shellcheck disable=SC2034 # Used by fn_fix_msg_start_nl and fn_fix_msg_end. + fixname="libstdc++5 i386" + fn_fix_msg_start_nl + fn_fetch_file "https://linuxgsm.download/libraries/libstdc++5-i386-3.3.6-34.tar.xz" "" "" "" "${tmpdir}" "libstdc++5-i386-3.3.6-34.tar.xz" "nochmodx" "norun" "noforce" "288a4cc9d6b7647f28c702028437e0f3" + fn_dl_extract "${tmpdir}" "libstdc++5-i386-3.3.6-34.tar.xz" "${serverfiles}" + fn_clear_tmp + fn_fix_msg_end +fi diff --git a/lgsm/modules/fix_codwaw.sh b/lgsm/modules/fix_codwaw.sh new file mode 100755 index 0000000000..fa18ccb1fa --- /dev/null +++ b/lgsm/modules/fix_codwaw.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# LinuxGSM fix_codwaw.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Call of Duty: World at War. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export GLIBC_TUNABLES="${GLIBC_TUNABLES:+${GLIBC_TUNABLES}:}glibc.rtld.execstack=2" diff --git a/lgsm/modules/fix_csgo.sh b/lgsm/modules/fix_csgo.sh index 8f5550ab53..979b470baf 100755 --- a/lgsm/modules/fix_csgo.sh +++ b/lgsm/modules/fix_csgo.sh @@ -7,11 +7,30 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" +# Server files are downloaded using App ID 740 (appid), but the App ID written to steam_appid.txt and steam.inf +# (clientappid) decides which client can connect: 4465480 for standalone CS:GO, 730 for the CS2 csgo_legacy branch. +# SteamCMD update/validate can revert these files, so this runs before every start. + # Fixes: server not always creating steam_appid.txt file. -if [ ! -f "${serverfiles}/steam_appid.txt" ]; then - fixname="730 steam_appid.txt" +# The server writes steam_appid.txt with a trailing null byte, which is removed before comparing. +if [ -n "${clientappid}" ] && { [ ! -f "${serverfiles}/steam_appid.txt" ] || [ "$(tr -d '\0' < "${serverfiles}/steam_appid.txt")" != "${clientappid}" ]; }; then + fixname="${clientappid} steam_appid.txt" + fn_fix_msg_start + if echo -n "${clientappid}" > "${serverfiles}/steam_appid.txt"; then + exitcode=0 + else + exitcode=1 + fi + fn_fix_msg_end +fi + +# Fixes: steam.inf not using the client App ID. +# steam.inf uses CRLF line endings, the whole value is replaced while keeping the line ending. +if [ -n "${clientappid}" ] && [ -f "${systemdir}/steam.inf" ] && grep -q "^appID=" "${systemdir}/steam.inf" && ! grep -qE "^appID=${clientappid}[[:cntrl:]]?$" "${systemdir}/steam.inf"; then + fixname="${clientappid} steam.inf" fn_fix_msg_start - echo -n "730" >> "${serverfiles}/steam_appid.txt" + sed -i "s/^appID=[^[:cntrl:]]*/appID=${clientappid}/" "${systemdir}/steam.inf" + exitcode=$? fn_fix_msg_end fi diff --git a/lgsm/modules/fix_cswon.sh b/lgsm/modules/fix_cswon.sh new file mode 100755 index 0000000000..2ba4bafff9 --- /dev/null +++ b/lgsm/modules/fix_cswon.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# LinuxGSM fix_cswon.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Counter-Strike WON2. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export GLIBC_TUNABLES="${GLIBC_TUNABLES:+${GLIBC_TUNABLES}:}glibc.cpu.hwcaps=-Fast_Unaligned_Load,-SSSE3" diff --git a/lgsm/modules/fix_ct.sh b/lgsm/modules/fix_ct.sh new file mode 100755 index 0000000000..b5c816b434 --- /dev/null +++ b/lgsm/modules/fix_ct.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# LinuxGSM fix_ct.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Craftopia. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +if [ -f "${servercfgfullpath}" ]; then + savepath="$(sed -n 's/^savePath=//p' "${servercfgfullpath}" | tr -d '\r')" + if [ -n "${savepath}" ] && [ "${savepath:0:1}" != "/" ]; then + oldsavedir="${serverfiles}${savepath%/}" + newsavedir="${serverfiles}/${savepath%/}" + if [ -e "${oldsavedir}" ] && [ -e "${newsavedir}" ]; then + fn_print_warn_nl "Craftopia saves found in both ${oldsavedir} and ${newsavedir}" + fn_script_log_warn "Craftopia saves found in both ${oldsavedir} and ${newsavedir}" + echo -e "* Keep the one you want in ${newsavedir}, remove the other, then start again." + else + if [ -e "${oldsavedir}" ]; then + fixname="move saves to ${newsavedir}" + fn_fix_msg_start + mkdir -p "$(dirname "${newsavedir}")" + mv "${oldsavedir}" "${newsavedir}" + exitcode=$? + fn_fix_msg_end + fi + if [ ! -e "${oldsavedir}" ]; then + fixname="savePath ${serverfiles}/${savepath}" + fn_fix_msg_start + sed -i "s|^savePath=[^\r]*|savePath=${serverfiles}/${savepath}|" "${servercfgfullpath}" + exitcode=$? + fn_fix_msg_end + fi + fi + fi +fi diff --git a/lgsm/modules/fix_hlwon.sh b/lgsm/modules/fix_hlwon.sh new file mode 100755 index 0000000000..5f8a0c47db --- /dev/null +++ b/lgsm/modules/fix_hlwon.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# LinuxGSM fix_hlwon.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Half-Life WON2. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export GLIBC_TUNABLES="${GLIBC_TUNABLES:+${GLIBC_TUNABLES}:}glibc.cpu.hwcaps=-Fast_Unaligned_Load,-SSSE3" diff --git a/lgsm/modules/fix_ios.sh b/lgsm/modules/fix_ios.sh new file mode 100755 index 0000000000..efb3c28831 --- /dev/null +++ b/lgsm/modules/fix_ios.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# LinuxGSM fix_ios.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with IOSoccer. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +# Fixes: IOSoccer 64-bit server stuck reloading the map #5023. +if [ -f "${servercfgfullpath}" ] && grep -qE '^\s*map\s' "${servercfgfullpath}"; then + fixname="remove map from ${servercfg}" + fn_fix_msg_start + sed -i -E 's|^(\s*map\s.*)$|// \1|' "${servercfgfullpath}" + fn_fix_msg_end +fi diff --git a/lgsm/modules/fix_mohaa.sh b/lgsm/modules/fix_mohaa.sh new file mode 100755 index 0000000000..a38e67e391 --- /dev/null +++ b/lgsm/modules/fix_mohaa.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# LinuxGSM fix_mohaa.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Medal of Honor: Allied Assault. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}" + +if ldd "${executabledir}/mohaa_lnxded" 2>&1 | grep -q "libstdc++\.so\.5 => not found"; then + # shellcheck disable=SC2034 # Used by fn_fix_msg_start_nl and fn_fix_msg_end. + fixname="libstdc++5 i386" + fn_fix_msg_start_nl + fn_fetch_file "https://linuxgsm.download/libraries/libstdc++5-i386-3.3.6-34.tar.xz" "" "" "" "${tmpdir}" "libstdc++5-i386-3.3.6-34.tar.xz" "nochmodx" "norun" "noforce" "288a4cc9d6b7647f28c702028437e0f3" + fn_dl_extract "${tmpdir}" "libstdc++5-i386-3.3.6-34.tar.xz" "${serverfiles}" + fn_clear_tmp + fn_fix_msg_end +fi diff --git a/lgsm/modules/fix_nd.sh b/lgsm/modules/fix_nd.sh new file mode 100755 index 0000000000..5d305348eb --- /dev/null +++ b/lgsm/modules/fix_nd.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# LinuxGSM fix_nd.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Nuclear Dawn. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +if [ ! -f "${serverfiles}/nucleardawn/gameinfo.txt" ]; then + fixname="game content" + fn_fix_msg_start_nl + steamcmdlog="${lgsmlogdir}/${selfname}-steamcmd.log" + rm -f "${steamcmdlog:?}" + if [ -d "${steamcmddir}" ]; then + cd "${steamcmddir}" || exit + fi + "${steamcmdcommand}" +login "${steamuser}" "${steampass}" +app_info_print 17710 +quit > /dev/null 2>&1 + "${steamcmdcommand}" +login "${steamuser}" "${steampass}" +download_depot 17710 17711 +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" + ndcontentdepot="$(grep -o 'Depot download complete : "[^"]*"' "${steamcmdlog}" | tail -1 | cut -d'"' -f2 | tr '\134' '/')" + if [[ "${ndcontentdepot}" == */depot_17711 ]]; then + if [ -f "${ndcontentdepot}/nucleardawn/gameinfo.txt" ]; then + tar -C "${ndcontentdepot}" -cf - . | tar -C "${serverfiles}" -xf - --skip-old-files + fi + rm -rf "${ndcontentdepot:?}" "${ndcontentdepot%/*}/state_17710_17711.patch" + fi + if [ -f "${serverfiles}/nucleardawn/gameinfo.txt" ]; then + exitcode=0 + else + exitcode=1 + fi + fn_fix_msg_end + if [ "${exitcode}" -ne 0 ]; then + fn_print_nl "* Nuclear Dawn game content requires a Steam account that owns Nuclear Dawn." + fn_print_nl "* Set steamuser and steampass in ${configdirserver}" + core_exit.sh + fi +fi diff --git a/lgsm/modules/fix_pvr.sh b/lgsm/modules/fix_pvr.sh index e4409bc37b..39d4fd3ee4 100755 --- a/lgsm/modules/fix_pvr.sh +++ b/lgsm/modules/fix_pvr.sh @@ -7,8 +7,22 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" -if [ ! -f "${serverfiles}/linux64/libc++.so" ] && [ -f "/usr/lib/x86_64-linux-gnu/libc++.so.1" ]; then - cp "/usr/lib/x86_64-linux-gnu/libc++.so.1" "${serverfiles}/linux64/libc++.so" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}:${serverfiles}/linux64" + +if ldd "${executabledir}/PavlovServer-Linux-Shipping" 2>&1 | grep -qE "libc\+\+(abi)?\.so\.1 => not found"; then + # shellcheck disable=SC2034 # Used by fn_fix_msg_start_nl and fn_fix_msg_end. + fixname="libc++ amd64" + fn_fix_msg_start_nl + fn_fetch_file "https://linuxgsm.download/libraries/libcxx-amd64-11.0.1-2.tar.xz" "" "" "" "${tmpdir}" "libcxx-amd64-11.0.1-2.tar.xz" "nochmodx" "norun" "noforce" "2a75a54c6637d217e3821220b0d5571f" + fn_dl_extract "${tmpdir}" "libcxx-amd64-11.0.1-2.tar.xz" "${serverfiles}/linux64" + fn_clear_tmp + fn_fix_msg_end fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}:${serverfiles}/linux64" +if [ ! -f "${serverfiles}/linux64/libc++.so" ]; then + if [ -f "/usr/lib/x86_64-linux-gnu/libc++.so.1" ]; then + cp "/usr/lib/x86_64-linux-gnu/libc++.so.1" "${serverfiles}/linux64/libc++.so" + elif [ -f "${serverfiles}/linux64/libc++.so.1" ]; then + cp -L "${serverfiles}/linux64/libc++.so.1" "${serverfiles}/linux64/libc++.so" + fi +fi diff --git a/lgsm/modules/fix_sfc.sh b/lgsm/modules/fix_sfc.sh index 70e5d04840..828ff95545 100755 --- a/lgsm/modules/fix_sfc.sh +++ b/lgsm/modules/fix_sfc.sh @@ -7,6 +7,8 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" +export GLIBC_TUNABLES="${GLIBC_TUNABLES:+${GLIBC_TUNABLES}:}glibc.rtld.execstack=2" + if [ ! -f "${serverfiles}/bin/datacache.so" ]; then ln -s "${serverfiles}/bin/datacache_srv.so" "${serverfiles}/bin/datacache.so" fi diff --git a/lgsm/modules/fix_steamcmd.sh b/lgsm/modules/fix_steamcmd.sh index 36bc378ac7..e3fc22722a 100755 --- a/lgsm/modules/fix_steamcmd.sh +++ b/lgsm/modules/fix_steamcmd.sh @@ -65,21 +65,16 @@ fi # place new hardlink for the file to the disk if [ ! -f "${steamclientsdk64}" ]; then - fixname="steamclient.so sdk64 hardlink" - fn_fix_msg_start - if [ ! -d "${steamsdk64}" ]; then - mkdir -p "${steamsdk64}" - fi - if [ -f "${HOME}/.steam/steamcmd/linux64/steamclient.so" ]; then - ln "${HOME}/.steam/steamcmd/linux64/steamclient.so" "${steamclientsdk64}" - elif [ -f "${steamcmddir}/linux64/steamclient.so" ]; then - ln "${steamcmddir}/linux64/steamclient.so" "${steamclientsdk64}" - elif [ -f "${HOME}/.local/share/Steam/steamcmd/linux64/steamclient.so" ]; then - ln "${HOME}/.local/share/Steam/steamcmd/linux64/steamclient.so" "${steamclientsdk64}" - else - fn_print_fail_nl "Could not copy any steamclient.so 64bit for the gameserver" - fi - fn_fix_msg_end + for steamclientso in "${HOME}/.steam/steamcmd/linux64/steamclient.so" "${steamcmddir}/linux64/steamclient.so" "${HOME}/.local/share/Steam/steamcmd/linux64/steamclient.so"; do + if [ -f "${steamclientso}" ]; then + fixname="steamclient.so sdk64 hardlink" + fn_fix_msg_start + mkdir -p "${steamsdk64}" + ln "${steamclientso}" "${steamclientsdk64}" + fn_fix_msg_end + break + fi + done fi # Helps fix: [S_API FAIL] SteamAPI_Init() failed; unable to locate a running instance of Steam,or a local steamclient.so. @@ -96,21 +91,16 @@ fi # place new hardlink for the file to the disk if [ ! -f "${steamclientsdk32}" ]; then - fixname="steamclient.so sdk32 link" - fn_fix_msg_start - if [ ! -d "${steamsdk32}" ]; then - mkdir -p "${steamsdk32}" - fi - if [ -f "${HOME}/.steam/steamcmd/linux32/steamclient.so" ]; then - ln "${HOME}/.steam/steamcmd/linux32/steamclient.so" "${steamclientsdk32}" - elif [ -f "${steamcmddir}/linux32/steamclient.so" ]; then - ln "${steamcmddir}/linux32/steamclient.so" "${steamclientsdk32}" - elif [ -f "${HOME}/.local/share/Steam/steamcmd/linux32/steamclient.so" ]; then - ln "${HOME}/.local/share/Steam/steamcmd/linux32/steamclient.so" "${steamclientsdk32}" - else - fn_print_fail_nl "Could not copy any steamclient.so 32bit for the gameserver" - fi - fn_fix_msg_end + for steamclientso in "${HOME}/.steam/steamcmd/linux32/steamclient.so" "${steamcmddir}/linux32/steamclient.so" "${HOME}/.local/share/Steam/steamcmd/linux32/steamclient.so"; do + if [ -f "${steamclientso}" ]; then + fixname="steamclient.so sdk32 link" + fn_fix_msg_start + mkdir -p "${steamsdk32}" + ln "${steamclientso}" "${steamclientsdk32}" + fn_fix_msg_end + break + fi + done fi # Helps fix: WARNING: Failed to load 32-bit libtinfo.so.5 or libncurses.so.5. diff --git a/lgsm/modules/fix_tf2.sh b/lgsm/modules/fix_tf2.sh index 1050264880..be13d01fdd 100755 --- a/lgsm/modules/fix_tf2.sh +++ b/lgsm/modules/fix_tf2.sh @@ -14,3 +14,10 @@ if [ -f "/etc/redhat-release" ] && [ ! -f "${serverfiles}/bin/libcurl-gnutls.so. ln -s "/usr/lib/libcurl.so.4" "${serverfiles}/bin/libcurl-gnutls.so.4" fn_fix_msg_end fi + +# Fixes: SourceMod extensions without 64-bit builds failing to load #4841. +if [ "${executable}" == "./srcds_run_64" ] && [ -d "${systemdir}/addons/sourcemod" ] && ! grep -qsE "^[[:blank:]]*executable=" "${configdirserver}/common.cfg" "${configdirserver}/secrets-common.cfg" "${configdirserver}/${selfname}.cfg" "${configdirserver}/secrets-${selfname}.cfg"; then + fn_print_info_nl "SourceMod detected, starting 32-bit server. Set executable=\"./srcds_run_64\" in ${selfname}.cfg to use 64-bit" + fn_script_log_info "SourceMod detected, starting 32-bit server. Set executable=\"./srcds_run_64\" in ${selfname}.cfg to use 64-bit" + executable="./srcds_run" +fi diff --git a/lgsm/modules/fix_ts.sh b/lgsm/modules/fix_ts.sh new file mode 100755 index 0000000000..b4a0519e89 --- /dev/null +++ b/lgsm/modules/fix_ts.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# LinuxGSM fix_ts.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with The Specialists. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export GLIBC_TUNABLES="${GLIBC_TUNABLES:+${GLIBC_TUNABLES}:}glibc.rtld.execstack=2" diff --git a/lgsm/modules/fix_ut.sh b/lgsm/modules/fix_ut.sh index 3da5c068c3..6771dfa687 100755 --- a/lgsm/modules/fix_ut.sh +++ b/lgsm/modules/fix_ut.sh @@ -5,9 +5,7 @@ # Website: https://linuxgsm.com # Description: Resolves issues with Unreal Tournament. +# shellcheck disable=SC2034 # Used by the module loader. moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" -#Set Binary Executable -echo -e "chmod +x ${executabledir}/${executable}" -chmod +x "${executabledir}/${executable}" -fn_sleep_time +export GLIBC_TUNABLES="${GLIBC_TUNABLES:+${GLIBC_TUNABLES}:}glibc.rtld.execstack=2" diff --git a/lgsm/modules/fix_ut99.sh b/lgsm/modules/fix_ut99.sh new file mode 100755 index 0000000000..f12f6759d0 --- /dev/null +++ b/lgsm/modules/fix_ut99.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# LinuxGSM fix_ut99.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Unreal Tournament 99. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +if [[ "${startparameters}" == *"-nohomedir"* ]] && [ -d "${HOME}/.utpg/System" ]; then + while IFS= read -r -d '' homeini; do + fixname="move $(basename "${homeini}") from ${HOME}/.utpg/System to ${systemdir}" + fn_fix_msg_start + mv --backup=numbered "${homeini}" "${systemdir}/" + exitcode=$? + fn_fix_msg_end + done < <(find "${HOME}/.utpg/System" -maxdepth 1 -type f -name "*.ini" -print0) +fi diff --git a/lgsm/modules/fix_vs.sh b/lgsm/modules/fix_vs.sh new file mode 100755 index 0000000000..03b3a3dfe4 --- /dev/null +++ b/lgsm/modules/fix_vs.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# LinuxGSM fix_vs.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Resolves issues with Vampire Slayer. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +export GLIBC_TUNABLES="${GLIBC_TUNABLES:+${GLIBC_TUNABLES}:}glibc.rtld.execstack=2" diff --git a/lgsm/modules/info_distro.sh b/lgsm/modules/info_distro.sh index 4ece95e4de..d90a62e3c9 100755 --- a/lgsm/modules/info_distro.sh +++ b/lgsm/modules/info_distro.sh @@ -14,6 +14,8 @@ if [ "${status}" == "1" ]; then gameserverpid="$(TERM=screen tmux -L "${socketname}" list-sessions -F "#{session_name} #{pane_pid}" | grep "^${sessionname} " | awk '{print $NF}')" if [ "${engine}" == "source" ]; then srcdslinuxpid="$(pgrep -P "${gameserverpid}" -x srcds_linux 2> /dev/null | head -n 1)" + elif [ "${querytype}" == "protocol-valve-won" ]; then + hldslinuxpid="$(pgrep -P "${gameserverpid}" -x hlds_i686 2> /dev/null | head -n 1)" elif [ "${engine}" == "goldsrc" ]; then hldslinuxpid="$(pgrep -P "${gameserverpid}" -x hlds_linux 2> /dev/null | head -n 1)" fi @@ -72,8 +74,14 @@ for distro_info in "${distro_info_array[@]}"; do done # Get virtual environment type. +virtualenvironment="unavailable" if [ "$(command -v systemd-detect-virt 2> /dev/null)" ]; then - virtualenvironment="$(systemd-detect-virt)" # e.g. kvm + virtualenvironment="$(systemd-detect-virt 2> /dev/null)" + virtualenvironmentstatus=$? + # systemd-detect-virt returns "none" with a nonzero status on bare metal. + if [ "${virtualenvironment}" != "none" ] && { [ "${virtualenvironmentstatus}" != "0" ] || [[ ! "${virtualenvironment}" =~ ^[a-zA-Z0-9_-]+$ ]]; }; then + virtualenvironment="unavailable" + fi fi # distroversioncsv is used for selecting the correct distro csv in data directory @@ -139,8 +147,62 @@ load="$(uptime | awk -F 'load average: ' '{ print $2 }')" # e.g 0.01, 0.05, 0.11 ## CPU information cpumodel="$(awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')" # e.g Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz -cpucores="$(awk -F: '/model name/ {core++} END {print core}' /proc/cpuinfo)" -cpufreqency="$(awk -F: '/cpu MHz/ {freq=$2} END {print freq}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')" # e.g 2394.503 +cpulogicalcores="$(find /sys/devices/system/cpu -maxdepth 1 -type d -name 'cpu[0-9]*' 2> /dev/null | while IFS= read -r cpu; do + if [ ! -f "${cpu}/online" ] || [ "$(< "${cpu}/online")" = "1" ]; then + echo "${cpu##*cpu}" + fi +done | wc -l | tr -d ' ')" +if [ -z "${cpumodel}" ] && [ "$(command -v lscpu 2> /dev/null)" ]; then + cpumodel="$(lscpu 2> /dev/null | sed -n 's/^Model name:[[:space:]]*//p')" +fi +if [ "${cpulogicalcores:-0}" -eq 0 ] && [ "$(command -v lscpu 2> /dev/null)" ]; then + cpulogicalcores="$(lscpu --parse=CPU 2> /dev/null | awk -F, '!/^#/ && $1 ~ /^[0-9]+$/ { count++ } END { print count+0 }')" +fi +if [ "${cpulogicalcores:-0}" -eq 0 ]; then + cpulogicalcores="$(awk -F: '/^[[:space:]]*processor[[:space:]]*:/ { count++ } END { print count+0 }' /proc/cpuinfo)" +fi +cpuphysicalcores="$(for cpu in /sys/devices/system/cpu/cpu[0-9]*; do + [ -d "${cpu}" ] || continue + [ ! -f "${cpu}/online" ] || [ "$(< "${cpu}/online")" = "1" ] || continue + if [ -r "${cpu}/topology/physical_package_id" ] && [ -r "${cpu}/topology/core_id" ]; then + printf '%s:%s\n' "$(< "${cpu}/topology/physical_package_id")" "$(< "${cpu}/topology/core_id")" + fi +done | sort -u | wc -l | tr -d ' ')" +if [ "${cpuphysicalcores:-0}" -eq 0 ] && [ "$(command -v lscpu 2> /dev/null)" ]; then + cpuphysicalcores="$(lscpu --parse=CORE,SOCKET 2> /dev/null | awk -F, '!/^#/ && NF >= 2 && $1 != "" && $2 != "" { cores[$1 ":" $2]=1 } END { for (core in cores) count++; print count+0 }')" +fi +if [ "${cpuphysicalcores:-0}" -eq 0 ]; then + cpuphysicalcores="$(awk -F: ' + BEGIN { package="0" } + /^[[:space:]]*physical id[[:space:]]*:/ { package=$2; gsub(/[[:space:]]/, "", package) } + /^[[:space:]]*core id[[:space:]]*:/ { core=$2; gsub(/[[:space:]]/, "", core); cores[package ":" core]=1; has_core=1 } + /^[[:space:]]*cpu cores[[:space:]]*:/ { package_cores=$2; gsub(/[[:space:]]/, "", package_cores); cores_per_package[package]=package_cores } + /^[[:space:]]*$/ { package="0" } + END { + if (has_core) { for (core in cores) total++; print total+0 } + else { for (package in cores_per_package) total+=cores_per_package[package]; print total+0 } + } + ' /proc/cpuinfo)" +fi +cpucores="${cpuphysicalcores}" +cpuphysicalcoresdisplay="${cpucores}" +if [ "${cpucores:-0}" -eq 0 ]; then + cpuphysicalcoresdisplay="unavailable" +fi +cpufrequencydata="$(awk -F: '/^[[:space:]]*cpu MHz[[:space:]]*:/ { value=$2; gsub(/[[:space:]]/, "", value); if (value ~ /^[0-9]+([.][0-9]+)?$/) print value }' /proc/cpuinfo)" +if [ -z "${cpufrequencydata}" ] && [ "$(command -v lscpu 2> /dev/null)" ]; then + cpufrequencydata="$(lscpu --parse=MHZ 2> /dev/null | awk -F, '!/^#/ && $1 ~ /^[0-9]+([.][0-9]+)?$/ { print $1 }')" +fi +read -r cpufreqency cpufrequencydisplay < <(printf '%s\n' "${cpufrequencydata}" | awk ' + NF && $1 ~ /^[0-9]+([.][0-9]+)?$/ { value=$1; if (!count || value < min) min=value; if (!count || value > max) max=value; sum+=value; count++ } + END { if (!count) printf "0.00 unavailable"; else if (min == max) printf "%.2f %.2fMHz", sum/count, min; else printf "%.2f %.2f-%.2fMHz", sum/count, min, max } + ') +cpufreqency="${cpufreqency:-0}" +export cpuphysicalcoresdisplay cpufrequencydisplay +export cpufrequencyaveragedisplay="${cpufreqency}" +if [ "${cpufrequencydisplay}" = "unavailable" ]; then + cpufrequencyaveragedisplay="unavailable" +fi # CPU usage of the game server pid if [ -n "${gameserverpid}" ]; then cpuused="$(ps --forest -o pcpu -g "${gameserverpid}" | awk '{s+=$1} END {print s}')" # integer @@ -169,8 +231,8 @@ if [ "$(command -v numfmt 2> /dev/null)" ]; then fi # Available RAM and swap. - physmemtotalmb="$(((physmemtotalkb + 512) / 1024))" # integer # integer - physmemtotalgb="$(((physmemtotalmb + 512) / 1024))" # integer # integer + physmemtotalmb="$(((physmemtotalkb + 512) / 1024))" # integer + physmemtotalgb="$(((physmemtotalmb + 512) / 1024))" # integer physmemtotal="$(numfmt --to=iec --from=iec --suffix=B "${physmemtotalkb}K")" # string physmemfree="$(numfmt --to=iec --from=iec --suffix=B "${physmemactualfreekb}K")" # string physmemused="$(numfmt --to=iec --from=iec --suffix=B "$((physmemtotalkb - physmemfreekb - physmembufferskb - physmemcachedkb - physmemreclaimablekb))K")" # string diff --git a/lgsm/modules/info_game.sh b/lgsm/modules/info_game.sh index d39e2d143d..3bfcf2634e 100755 --- a/lgsm/modules/info_game.sh +++ b/lgsm/modules/info_game.sh @@ -31,7 +31,7 @@ fn_info_game_ini() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(sed -n '/^\<'"${2}"'\>/ { s/.*= *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')\"" + printf -v "${1}" '%s' "$(sed -n '/^\<'"${2}"'\>/ { s/.*= *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')" configtype="ini" } @@ -56,7 +56,7 @@ fn_info_game_keyvalue_pairs_equals() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(sed -n '/^\<'"${2}"'\>/ { s/.*= *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')\"" + printf -v "${1}" '%s' "$(sed -n '/^\<'"${2}"'\>/ { s/.*= *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')" configtype="keyvalue_pairs" } @@ -81,7 +81,7 @@ fn_info_game_keyvalue_pairs_space() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(sed -n '/^\<'"${2}"'\>/ { s/.* *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')\"" + printf -v "${1}" '%s' "$(sed -n '/^\<'"${2}"'\>/ { s/.* *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')" configtype="keyvalue_pairs" } @@ -106,7 +106,7 @@ fn_info_game_quakec() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(sed -n '/[[:space:]]\<'"${2}"'\>/ { s/.* *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')\"" + printf -v "${1}" '%s' "$(sed -n '/[[:space:]]\<'"${2}"'\>/ { s/.* *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')" configtype="quakec" } @@ -118,7 +118,7 @@ fn_info_game_json() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(jq -r "${2}" "${servercfgparse}")\"" + printf -v "${1}" '%s' "$(jq -r "${2}" "${servercfgparse}")" configtype="json" } @@ -144,7 +144,7 @@ fn_info_game_sqf() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(sed -n '/^\<'"${2}"'\>/ { s/.*= *"\?\([^"]*\)"\?/\1/;s/;$//p;q }' "${servercfgparse}" | tr -d '\r')\"" + printf -v "${1}" '%s' "$(sed -n '/^\<'"${2}"'\>/ { s/.*= *"\?\([^"]*\)"\?/\1/;s/;$//p;q }' "${servercfgparse}" | tr -d '\r')" configtype="sqf" } @@ -156,7 +156,7 @@ fn_info_game_xml() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(xmllint --xpath "string(${2})" "${servercfgparse}")\"" + printf -v "${1}" '%s' "$(xmllint --xpath "string(${2})" "${servercfgparse}")" configtype="xml" } @@ -182,7 +182,7 @@ fn_info_game_valve_keyvalues() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(sed -n '/^\<'"${2}"'\>/ { s/.* *"\([^"]*\)".*/\1/p;q }' "${servercfgparse}" | tr -d '\r')\"" + printf -v "${1}" '%s' "$(sed -n '/^\<'"${2}"'\>/ { s/.* *"\([^"]*\)".*/\1/p;q }' "${servercfgparse}" | tr -d '\r')" configtype="valve_keyvalues" } @@ -207,7 +207,7 @@ fn_info_game_java_properties() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(sed -n '/^\<'"${2}"'\>/ { s/.*= *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')\"" + printf -v "${1}" '%s' "$(sed -n '/^\<'"${2}"'\>/ { s/.*= *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')" configtype="java" } @@ -230,7 +230,7 @@ fn_info_game_lua() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(sed -n '/^[[:space:]]*\<'"${2}"'\>/ { s/.*= *"\?\([^"]*\)"\?/\1/;s#,.*##;p;q }' "${servercfgparse}" | tr -d '\r')\"" + printf -v "${1}" '%s' "$(sed -n '/^[[:space:]]*\<'"${2}"'\>/ { s/.*= *"\?\([^"]*\)"\?/\1/;s#,.*##;p;q }' "${servercfgparse}" | tr -d '\r')" configtype="lua" } @@ -255,7 +255,7 @@ fn_info_game_pc_config() { else servercfgparse="${servercfgfullpath}" fi - eval "${1}=\"$(sed -n '/^\<'"${2}"'\>/ { s/.*: *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')\"" + printf -v "${1}" '%s' "$(sed -n '/^\<'"${2}"'\>/ { s/.*: *\"\?\([^"]*\)\"\?/\1/p;q }' "${servercfgparse}" | tr -d '\r')" configtype="pc_config" } @@ -757,8 +757,12 @@ fn_info_game_ts3() { fn_info_game_ini "httpqueryport" "query_http_port" fn_info_game_ini "httpsqueryport" "query_https_port" fn_info_game_ini "queryport" "query_port" + fn_info_game_ini "configqueryip" "query_ip" fn_info_game_ini "sshqueryport" "query_ssh_port" fi + # query_ip can list several addresses (e.g. "0.0.0.0, ::"), use the first. + configqueryip="${configqueryip%%,*}" + configqueryip="${configqueryip// /}" configip="${configip:-"0.0.0.0"}" dbplugin="${dbplugin:-"NOT SET"}" fileport="${fileport:-"0"}" @@ -830,9 +834,9 @@ fn_info_game_ut3() { fn_info_game_ini "maxplayers" "MaxPlayers" fn_info_game_ini "servername" "ServerName" fn_info_game_ini "serverpassword" "GamePassword" - fn_info_game_ini "httpenabled" "bEnabled" + fn_info_game_ini "httpenabled" "bEnabled" "${servercfgdir}/UTWeb.ini" fn_info_game_ini "httppassword" "AdminPassword" - fn_info_game_ini "httpport" "ListenPort" + fn_info_game_ini "httpport" "ListenPort" "${servercfgdir}/UTWeb.ini" fi adminpassword="${adminpassword:-"NOT SET"}" defaultmap="${defaultmap:-"NOT SET"}" @@ -971,6 +975,27 @@ fn_info_game_bf1942() { serverpassword="${serverpassword:-"NOT SET"}" } +# Config Type: json +# Parameters: false +# Comment: none +# Example: "name": "SERVERNAME", +# Filetype: json +fn_info_game_bfe() { + if [ -f "${servercfgfullpath}" ]; then + fn_info_game_json "configip" ".bind // empty" + fn_info_game_json "discoveryport" ".discoveryPort // empty" + fn_info_game_json "maxplayers" ".maxPlayers // empty" + fn_info_game_json "port" ".gamePort // empty" + fn_info_game_json "servername" ".name // empty" + fi + configip="${configip:-"0.0.0.0"}" + discoveryport="${discoveryport:-"18452"}" + maxplayers="${maxplayers:-"64"}" + port="${port:-"18451"}" + queryport="${port}" + servername="${servername:-"NOT SET"}" +} + # Config Type: con # Parameters: true # Comment: # or // @@ -1001,11 +1026,20 @@ fn_info_game_bfv() { fn_info_game_bt() { if [ -f "${servercfgfullpath}" ]; then fn_info_game_xml "maxplayers" "/serversettings/@MaxPlayers" + if [ -z "${maxplayers}" ]; then + fn_info_game_xml "maxplayers" "/serversettings/@maxplayers" + fi fn_info_game_xml "port" "/serversettings/@port" fn_info_game_xml "queryport" "/serversettings/@queryport" - fn_info_game_xml "servername" "/serversettings/@name" + fn_info_game_xml "servername" "/serversettings/@ServerName" + if [ -z "${servername}" ]; then + fn_info_game_xml "servername" "/serversettings/@name" + fi fn_info_game_xml "serverpassword" "/serversettings/@password" fn_info_game_xml "tickrate" "/serversettings/@TickRate" + if [ -z "${tickrate}" ]; then + fn_info_game_xml "tickrate" "/serversettings/@tickrate" + fi fi maxplayers="${maxplayers:-"0"}" port="${port:-"0"}" @@ -1039,6 +1073,25 @@ fn_info_game_cd() { steamport="${steamport:-"0"}" } +# Config Type: ini +# Parameters: true +# Comment: ; or # +# Example: ServerPassword=PASSWORD +# Filetype: ini +fn_info_game_ce() { + if [ -f "${servercfgfullpath}" ]; then + fn_info_game_ini "adminpassword" "AdminPassword" + fn_info_game_ini "serverpassword" "ServerPassword" + fi + adminpassword="${adminpassword:-"NOT SET"}" + maxplayers="${maxplayers:-"0"}" + port="${port:-"0"}" + queryport="${queryport:-"0"}" + rawport="$((port + 1))" + servername="${servername:-"NOT SET"}" + serverpassword="${serverpassword:-"NOT SET"}" +} + # Config Type: json # Parameters: true # Comment: // or /* */ @@ -1287,6 +1340,24 @@ fn_info_game_etl() { serverpassword="${serverpassword:-"NOT SET"}" } +# Config Type: Custom (key value pairs) +# Comment: # +# Example: sv_hostname "SERVERNAME" +# Filetype: cfg +fn_info_game_fivem() { + if [ -f "${servercfgfullpath}" ]; then + servername="$(sed -n 's/^sv_hostname[[:space:]]\+"\?\([^"]*\)"\?.*/\1/p' "${servercfgfullpath}" | head -1 | tr -d '\r')" + maxplayers="$(sed -n 's/^sv_maxclients[[:space:]]\+\([0-9]*\).*/\1/p' "${servercfgfullpath}" | head -1)" + rconpassword="$(sed -n 's/^rcon_password[[:space:]]\+"\?\([^"]*\)"\?.*/\1/p' "${servercfgfullpath}" | head -1 | tr -d '\r')" + port="$(sed -n 's/^endpoint_add_udp[[:space:]]\+"\?[^:"]*:\([0-9]*\)"\?.*/\1/p' "${servercfgfullpath}" | head -1)" + fi + maxplayers="${maxplayers:-"0"}" + port="${port:-"0"}" + queryport="${port}" + rconpassword="${rconpassword:-"NOT SET"}" + servername="${servername:-"NOT SET"}" +} + # Config Type: json # Parameters: true # Comment: // or /* */ @@ -1350,6 +1421,27 @@ fn_info_game_hz() { servername="${servername:-"NOT SET"}" } +# Config Type: json +# Parameters: true +# Comment: +# Example: "ServerName": "SERVERNAME" +# Filetype: json +fn_info_game_hyt() { + # config.json is created by the server on first start. + if [ -f "${servercfgfullpath}" ]; then + fn_info_game_json "maxplayers" ".MaxPlayers // empty" + fn_info_game_json "servername" ".ServerName // empty" + fn_info_game_json "serverpassword" ".Password // empty" + fi + configtype="json" + configip="${ip:-"0.0.0.0"}" + maxplayers="${maxplayers:-"0"}" + port="${port:-"5520"}" + queryport="${port}" + servername="${servername:-"NOT SET"}" + serverpassword="${serverpassword:-"NOT SET"}" +} + # Config Type: parameters # Parameters: true # Comment: @@ -1442,6 +1534,27 @@ fn_info_game_jk2() { serverversion="${serverversion:-"NOT SET"}" } +# Config Type: QuakeC +# Parameters: true +# Comment: // or /* */ +# Example: set sv_hostname "SERVERNAME" +# Filetype: cfg +fn_info_game_jk3() { + if [ -f "${servercfgfullpath}" ]; then + fn_info_game_quakec "maxplayers" "sv_maxclients" + fn_info_game_quakec "rconpassword" "rconpassword" + fn_info_game_quakec "servername" "sv_hostname" + fn_info_game_quakec "serverpassword" "g_password" + fi + defaultmap="${defaultmap:-"NOT SET"}" + maxplayers="${maxplayers:-"0"}" + port="${port:-"0"}" + queryport="${port}" + rconpassword="${rconpassword:-"NOT SET"}" + servername="${servername:-"NOT SET"}" + serverpassword="${serverpassword:-"NOT SET"}" +} + # Config Type: Java properties # Comment: # or ! # Example: motd=SERVERNAME @@ -1799,6 +1912,49 @@ fn_info_game_ro() { unreal2queryport="$((port + 1))" # Unreal2 Query Port } +# Config Type: ini +# Parameters: true +# Comment: ; or # +# Example: ServerName=SERVERNAME +# Filetype: ini +fn_info_game_rsdw() { + if [ -f "${servercfgfullpath}" ]; then + fn_info_game_ini "adminpassword" "AdminPassword" + fn_info_game_ini "ownerid" "OwnerId" + fn_info_game_ini "servername" "ServerName" + fn_info_game_ini "serverpassword" "WorldPassword" + fn_info_game_ini "worldname" "DefaultWorldName" + fi + adminpassword="${adminpassword:-"NOT SET"}" + ownerid="${ownerid:-"NOT SET"}" + port="${port:-"0"}" + queryport="${port:-"0"}" + servername="${servername:-"NOT SET"}" + serverpassword="${serverpassword:-"NOT SET"}" + worldname="${worldname:-"NOT SET"}" +} + +# Config Type: AngelScript (start_server command) +# Comment: // +# Example: server_name='SERVERNAME' +# Filetype: as +fn_info_game_rwr() { + local startscriptfile="${serverfiles}/${startpackage:-media/packages/vanilla}/scripts/${startscript}" + if [ ! -f "${startscriptfile}" ]; then + startscriptfile="${servercfgfullpath}" + fi + if [ -f "${startscriptfile}" ]; then + servername="$(sed -n "s/.*server_name='\([^']*\)'.*/\1/p" "${startscriptfile}" | head -1)" + port="$(sed -n "s/.*server_port='\([0-9]*\)'.*/\1/p" "${startscriptfile}" | head -1)" + maxplayers="$(sed -n "s/.*max_players='\([0-9]*\)'.*/\1/p" "${startscriptfile}" | head -1)" + gamemode="$(sed -n "s/.*mode='\([^']*\)'.*/\1/p" "${startscriptfile}" | head -1)" + fi + servername="${servername:-"NOT SET"}" + port="${port:-"0"}" + queryport="${port}" + maxplayers="${maxplayers:-"0"}" + gamemode="${gamemode:-"NOT SET"}" +} # Config Type: QuakeC # Comment: // or /* */ # Example: set sv_hostname "SERVERNAME" @@ -1960,7 +2116,7 @@ fn_info_game_sdtd() { fn_info_game_xml "serverpassword" "/ServerSettings/property[@name='ServerPassword']/@value" fn_info_game_xml "port" "/ServerSettings/property[@name='ServerPort']/@value" fn_info_game_xml "telnetenabled" "/ServerSettings/property[@name='TelnetEnabled']/@value" - fn_info_game_xml "telnetpass" "/ServerSettings/property[@name='TelnetPassword']/@value" + fn_info_game_xml "telnetpassword" "/ServerSettings/property[@name='TelnetPassword']/@value" fn_info_game_xml "telnetport" "/ServerSettings/property[@name='TelnetPort']/@value" fn_info_game_xml "worldname" "/ServerSettings/property[@name='GameWorld']/@value" fi @@ -1980,7 +2136,7 @@ fn_info_game_sdtd() { if [ -z "${telnetpassword}" ]; then telnetip="127.0.0.1" fi - telnetpass="${telnetpass:-"NOT SET"}" + telnetpassword="${telnetpassword:-"NOT SET"}" telnetport="${telnetport:-"0"}" worldname="${worldname:-"NOT SET"}" @@ -1991,8 +2147,7 @@ fn_info_game_sf() { # Parameters servername="${servername:-"NOT SET"}" port="${port:-"0"}" - queryport="${queryport:-"0"}" - beaconport="${beaconport:-"0"}" + queryport="${port}" reliableport="${reliableport:-"0"}" } @@ -2061,10 +2216,10 @@ fn_info_game_source() { fn_info_game_valve_keyvalues "servername" "hostname" fn_info_game_valve_keyvalues "serverpassword" "sv_password" fi - # Steamport can be between 26901-26910 and is normally automatically set. - # Some servers might support -steamport parameter to set - if [ "${steamport}" == "0" ] || [ -v "${steamport}" ]; then - steamport="$(echo "${ssinfo}" | grep "${srcdslinuxpid}" | awk '{print $5}' | grep ":269" | cut -d ":" -f2)" + # Detect the optional Steam port from this server's UDP sockets in the 269xx range. + # Keep an explicitly configured port, including ports outside the default range. + if { [ -z "${steamport}" ] || [ "${steamport}" == "0" ]; } && [ -n "${srcdslinuxpid}" ]; then + steamport="$(echo "${ssinfo}" | awk -v pid="${srcdslinuxpid}" '$1 == "udp" && $0 ~ ("pid=" pid ",") { port = $5; sub(/^.*:/, "", port); if (port ~ /^269[0-9][0-9]$/) { print port; exit } }')" fi clientport="${clientport:-"0"}" defaultmap="${defaultmap:-"NOT SET"}" @@ -2176,6 +2331,29 @@ fn_info_game_vh() { servername="${servername:-"NOT SET"}" } +# Config Type: Key Value Pairs (Equals Delimited) +# Comment: # +fn_info_game_luanti() { + if [ -f "${servercfgfullpath}" ]; then + fn_info_game_keyvalue_pairs_equals "servername" "server_name" + fn_info_game_keyvalue_pairs_equals "serverpassword" "default_password" + fn_info_game_keyvalue_pairs_equals "maxplayers" "max_users" + fn_info_game_keyvalue_pairs_equals "configip" "bind_address" + fi + servername="${servername:-"NOT SET"}" + serverpassword="${serverpassword:-"NOT SET"}" + maxplayers="${maxplayers:-"20"}" + configip="${configip:-"0.0.0.0"}" + queryport="${port}" +} + +# Parameters: true +fn_info_game_openra() { + port="${port:-"1234"}" + queryport="${port}" + servername="${servername:-"NOT SET"}" +} + # Config Type: json # Parameters: false # Comment: // or /* */ @@ -2331,6 +2509,8 @@ elif [ "${shortname}" == "av" ]; then fn_info_game_av elif [ "${shortname}" == "bf1942" ]; then fn_info_game_bf1942 +elif [ "${shortname}" == "bfe" ]; then + fn_info_game_bfe elif [ "${shortname}" == "bfv" ]; then fn_info_game_bfv elif [ "${shortname}" == "bo" ]; then @@ -2339,6 +2519,8 @@ elif [ "${shortname}" == "bt" ]; then fn_info_game_bt elif [ "${shortname}" == "btl" ]; then fn_info_game_btl +elif [ "${shortname}" == "ce" ]; then + fn_info_game_ce elif [ "${shortname}" == "ck" ]; then fn_info_game_ck elif [ "${shortname}" == "cmw" ]; then @@ -2371,10 +2553,14 @@ elif [ "${shortname}" == "etl" ]; then fn_info_game_etl elif [ "${shortname}" == "fctr" ]; then fn_info_game_fctr +elif [ "${shortname}" == "fivem" ]; then + fn_info_game_fivem elif [ "${shortname}" == "hw" ]; then fn_info_game_hw elif [ "${shortname}" == "hz" ]; then fn_info_game_hz +elif [ "${shortname}" == "hyt" ]; then + fn_info_game_hyt elif [ "${shortname}" == "inss" ]; then fn_info_game_inss elif [ "${shortname}" == "jc2" ]; then @@ -2383,6 +2569,8 @@ elif [ "${shortname}" == "jc3" ]; then fn_info_game_jc3 elif [ "${shortname}" == "jk2" ]; then fn_info_game_jk2 +elif [ "${shortname}" == "jk3" ]; then + fn_info_game_jk3 elif [ "${shortname}" == "kf" ]; then fn_info_game_kf elif [ "${shortname}" == "kf2" ]; then @@ -2427,8 +2615,12 @@ elif [ "${shortname}" == "qw" ]; then fn_info_game_qw elif [ "${shortname}" == "ro" ]; then fn_info_game_ro +elif [ "${shortname}" == "rsdw" ]; then + fn_info_game_rsdw elif [ "${shortname}" == "rtcw" ]; then fn_info_game_rtcw +elif [ "${shortname}" == "rwr" ]; then + fn_info_game_rwr elif [ "${shortname}" == "rust" ]; then fn_info_game_rust elif [ "${shortname}" == "rw" ]; then @@ -2439,7 +2631,7 @@ elif [ "${shortname}" == "sb" ]; then fn_info_game_sb elif [ "${shortname}" == "sbots" ]; then fn_info_game_sbots -elif [ "${shortname}" == "scpsl" ] || [ "${shortname}" == "scpslsm" ]; then +elif [ "${shortname}" == "scpsl" ]; then fn_info_game_scpsl elif [ "${shortname}" == "sdtd" ]; then fn_info_game_sdtd @@ -2483,6 +2675,10 @@ elif [ "${shortname}" == "ut99" ]; then fn_info_game_ut99 elif [ "${shortname}" == "vh" ]; then fn_info_game_vh +elif [ "${shortname}" == "luanti" ]; then + fn_info_game_luanti +elif [ "${shortname}" == "orar" ]; then + fn_info_game_openra elif [ "${shortname}" == "vints" ]; then fn_info_game_vints elif [ "${shortname}" == "vpmc" ]; then diff --git a/lgsm/modules/info_messages.sh b/lgsm/modules/info_messages.sh index 1ef9508303..635f9f673a 100755 --- a/lgsm/modules/info_messages.sh +++ b/lgsm/modules/info_messages.sh @@ -111,6 +111,7 @@ fn_info_messages_distro() { # Uptime: 16d, 5h, 18m # tmux: tmux 3.0a # glibc: 2.31 + # Missing dependencies: lib32gcc-s1 steamcmd echo -e "" echo -e "${bold}${lightyellow}Distro Details${default}" @@ -128,6 +129,11 @@ fn_info_messages_distro() { if [ -n "${javaram}" ]; then echo -e "${lightblue}Java:\t${default}${javaversion}" fi + if [ "${#array_deps_missing[@]}" != "0" ]; then + echo -e "${lightblue}Missing dependencies:\t${red}${array_deps_missing[*]}${default}" + elif [ "${depcheckunavailable}" == "1" ]; then + echo -e "${lightblue}Missing dependencies:\t${default}dependency checking unavailable for ${distroname}" + fi } | column -s $'\t' -t } @@ -162,8 +168,9 @@ fn_info_messages_server_resource() { { echo -e "${bold}${lightyellow}CPU\t${default}" echo -e "${lightblue}Model:\t${default}${cpumodel}" - echo -e "${lightblue}Cores:\t${default}${cpucores}" - echo -e "${lightblue}Frequency:\t${default}${cpufreqency}MHz" + echo -e "${lightblue}Cores:\t${default}${cpuphysicalcoresdisplay}" + echo -e "${lightblue}Threads:\t${default}${cpulogicalcores}" + echo -e "${lightblue}Frequency:\t${default}${cpufrequencydisplay} per logical CPU" echo -e "${lightblue}Avg Load:\t${default}${load}" } | column -s $'\t' -t echo -e "" @@ -550,6 +557,8 @@ fn_info_messages_script() { # Email alert: off # Gotify alert: off # IFTTT alert: off + # Matrix alert: off + # ntfy alert: off # Pushbullet alert: off # Pushover alert: off # Rocketchat alert: off @@ -601,6 +610,14 @@ fn_info_messages_script() { if [ "${iftttalert}" == "on" ]; then echo -e "${lightblue}IFTTT alert:\t${default}${iftttalert}" fi + # Matrix alert + if [ "${matrixalert}" == "on" ]; then + echo -e "${lightblue}Matrix alert:\t${default}${matrixalert}" + fi + # ntfy alert + if [ "${ntfyalert}" == "on" ]; then + echo -e "${lightblue}ntfy alert:\t${default}${ntfyalert}" + fi # Pushbullet alert if [ "${pushbulletalert}" == "on" ]; then echo -e "${lightblue}Pushbullet alert:\t${default}${pushbulletalert}" @@ -719,7 +736,7 @@ fn_info_messages_ports_edit() { startparameterslocation="${red}UNKNOWN${default}" # engines/games that require editing in the config file. - local ports_edit_array=("ac" "arma3" "armar" "bo" "bt" "ct" "dst" "eco" "idtech2" "idtech3" "idtech3_ql" "jc2" "jc3" "lwjgl2" "mcb" "nec" "pc" "pc2" "prism3d" "pz" "qw" "refractor" "renderware" "rw" "sb" "sdtd" "st" "stn" "ts3" "tw" "terraria" "unreal" "unreal2" "unreal3" "vints" "xnt" "wurm") + local ports_edit_array=("ac" "arma3" "armar" "bfe" "bo" "bt" "ct" "dst" "eco" "fivem" "idtech2" "idtech3" "idtech3_ql" "jc2" "jc3" "lwjgl2" "mcb" "nec" "pc" "pc2" "prism3d" "pz" "qw" "refractor" "renderware" "rw" "rwr" "sb" "sdtd" "st" "stn" "ts3" "tw" "terraria" "unreal" "unreal2" "unreal3" "vints" "xnt" "wurm") for port_edit in "${ports_edit_array[@]}"; do if [ "${shortname}" == "ut3" ]; then startparameterslocation="${servercfgdir}/UTWeb.ini" @@ -730,7 +747,7 @@ fn_info_messages_ports_edit() { fi done # engines/games that require editing the start parameters. - local ports_edit_array=("av" "ck" "col" "cs2" "fctr" "goldsrc" "hcu" "hw" "iw3.0" "ioquake3" "pw" "qfusion" "rust" "scpsl" "scpslsm" "sf" "sol" "spark" "source" "unreal4" "arma3" "dayz" "unt" "vh") + local ports_edit_array=("av" "ce" "ck" "col" "cs2" "fctr" "goldsrc" "hcu" "hw" "hyt" "luanti" "iw3.0" "ioquake3" "openra" "pw" "qfusion" "rsdw" "rust" "scpsl" "sf" "sol" "spark" "source" "unreal4" "arma3" "dayz" "unt" "vh") for port_edit in "${ports_edit_array[@]}"; do if [ "${engine}" == "${port_edit}" ] || [ "${gamename}" == "${port_edit}" ] || [ "${shortname}" == "${port_edit}" ]; then startparameterslocation="${configdirserver}" @@ -748,18 +765,28 @@ fn_info_messages_ports() { portcommand="ss -tuplwn | grep AvorionServer" elif [ "${shortname}" == "bf1942" ]; then portcommand="ss -tuplwn | grep bf1942_lnxded" + elif [ "${shortname}" == "bfe" ]; then + portcommand="ss -tuplwn | grep MainThread" elif [ "${shortname}" == "bfv" ]; then portcommand="ss -tuplwn | grep bfv_linded" + elif [ "${shortname}" == "ce" ]; then + portcommand="ss -tuplwn | grep ConanSandbox" elif [ "${shortname}" == "dayz" ]; then portcommand="ss -tuplwn | grep enfMain" elif [ "${shortname}" == "q4" ]; then portcommand="ss -tuplwn | grep q4ded.x86" - elif [ "${shortname}" == "mc" ] || [ "${shortname}" == "nec" ] || [ "${shortname}" == "pmc" ] || [ "${shortname}" == "vpmc" ] || [ "${shortname}" == "wmc" ]; then + elif [ "${shortname}" == "fivem" ]; then + portcommand="ss -tuplwn | grep ld-musl" + elif [ "${shortname}" == "rwr" ]; then + portcommand="ss -tuplwn | grep rwr_server" + elif [ "${shortname}" == "hyt" ] || [ "${shortname}" == "mc" ] || [ "${shortname}" == "nec" ] || [ "${shortname}" == "pmc" ] || [ "${shortname}" == "vpmc" ] || [ "${shortname}" == "wmc" ]; then portcommand="ss -tuplwn | grep java" elif [ "${shortname}" == "terraria" ]; then portcommand="ss -tuplwn | grep Main" elif [ "${shortname}" == "sm" ]; then portcommand="ss -tuplwn | grep WSServer-Linux" + elif [ "${querytype}" == "protocol-valve-won" ]; then + portcommand="ss -tuplwn | grep hlds_i686" elif [ "${engine}" == "source" ]; then portcommand="ss -tuplwn | grep srcds_linux" elif [ "${engine}" == "goldsrc" ]; then @@ -907,6 +934,15 @@ fn_info_messages_bf1942() { } | column -s $'\t' -t } +fn_info_messages_bfe() { + { + fn_port "header" + fn_port "Game" port udp + fn_port "Query" queryport tcp + fn_port "LAN Discovery" discoveryport udp + } | column -s $'\t' -t +} + fn_info_messages_bfv() { { fn_port "header" @@ -949,6 +985,15 @@ fn_info_messages_cd() { } | column -s $'\t' -t } +fn_info_messages_ce() { + { + fn_port "header" + fn_port "Game" port udp + fn_port "Raw UDP" rawport udp + fn_port "Query" queryport udp + } | column -s $'\t' -t +} + fn_info_messages_ck() { { fn_port "header" @@ -1089,6 +1134,14 @@ fn_info_messages_etl() { } | column -s $'\t' -t } +fn_info_messages_fivem() { + { + fn_port "header" + fn_port "Game" port tcp + fn_port "Game" port udp + } | column -s $'\t' -t +} + fn_info_messages_fctr() { { fn_port "header" @@ -1101,7 +1154,11 @@ fn_info_messages_goldsrc() { { fn_port "header" fn_port "Game" port udp - fn_port "Query" queryport tcp + if [ "${querytype}" == "protocol-valve-won" ]; then + fn_port "Query" queryport udp + else + fn_port "Query" queryport tcp + fi fn_port "Client" clientport udp } | column -s $'\t' -t } @@ -1131,6 +1188,13 @@ fn_info_messages_hz() { } | column -s $'\t' -t } +fn_info_messages_hyt() { + { + fn_port "header" + fn_port "Game" port udp + } | column -s $'\t' -t +} + fn_info_messages_ins() { { fn_port "header" @@ -1176,6 +1240,13 @@ fn_info_messages_jk2() { } | column -s $'\t' -t } +fn_info_messages_jk3() { + { + fn_port "header" + fn_port "Game" port udp + } | column -s $'\t' -t +} + fn_info_messages_kf() { { fn_port "header" @@ -1412,6 +1483,35 @@ fn_info_messages_ro() { } | column -s $'\t' -t } +fn_info_messages_rsdw() { + { + fn_port "header" + fn_port "Game" port udp + } | column -s $'\t' -t + echo -e "" + echo -e "${bold}${lightgreen}${gamename} Game Settings${default}" + fn_messages_separator + { + echo -e "${lightblue}World name:\t${default}${worldname}" + echo -e "${lightblue}Owner ID:\t${default}${ownerid}" + } | column -s $'\t' -t +} + +fn_info_messages_rwr() { + { + fn_port "header" + fn_port "Game" port udp + } | column -s $'\t' -t + echo -e "" + echo -e "${bold}${lightgreen}${gamename} Game Settings${default}" + fn_messages_separator + { + echo -e "${lightblue}Start package:\t${default}${startpackage}" + echo -e "${lightblue}Start script:\t${default}${startscript}" + echo -e "${lightblue}Game mode:\t${default}${gamemode}" + } | column -s $'\t' -t +} + fn_info_messages_rtcw() { { fn_port "header" @@ -1502,8 +1602,7 @@ fn_info_messages_sf() { { fn_port "header" fn_port "Game" port udp - fn_port "Query" queryport udp - fn_port "Beacon" beaconport udp + fn_port "Server API" port tcp fn_port "ReliableMessaging" reliableport tcp } | column -s $'\t' -t } @@ -1559,7 +1658,7 @@ fn_info_messages_source() { fn_port "RCON" rconport tcp fn_port "SourceTV" sourcetvport udp # Will not show if unavailable - if [ "${steamport}" == "0" ] || [ -v "${steamport}" ]; then + if [ -n "${steamport}" ] && [ "${steamport}" != "0" ]; then fn_port "Steam" steamport udp fi fn_port "Client" clientport udp @@ -1750,6 +1849,20 @@ fn_info_messages_vh() { } | column -s $'\t' -t } +fn_info_messages_luanti() { + { + fn_port "header" + fn_port "Game" port udp + } | column -s $'\t' -t +} + +fn_info_messages_openra() { + { + fn_port "header" + fn_port "Game" port tcp + } | column -s $'\t' -t +} + fn_info_messages_vints() { { fn_port "header" @@ -1812,6 +1925,8 @@ fn_info_messages_select_engine() { fn_info_messages_av elif [ "${shortname}" == "bf1942" ]; then fn_info_messages_bf1942 + elif [ "${shortname}" == "bfe" ]; then + fn_info_messages_bfe elif [ "${shortname}" == "bfv" ]; then fn_info_messages_bfv elif [ "${shortname}" == "bo" ]; then @@ -1820,6 +1935,8 @@ fn_info_messages_select_engine() { fn_info_messages_bt elif [ "${shortname}" == "btl" ]; then fn_info_messages_btl + elif [ "${shortname}" == "ce" ]; then + fn_info_messages_ce elif [ "${shortname}" == "ck" ]; then fn_info_messages_ck elif [ "${shortname}" == "cs2" ]; then @@ -1854,12 +1971,16 @@ fn_info_messages_select_engine() { fn_info_messages_etl elif [ "${shortname}" == "fctr" ]; then fn_info_messages_fctr + elif [ "${shortname}" == "fivem" ]; then + fn_info_messages_fivem elif [ "${shortname}" == "hcu" ]; then fn_info_messages_hcu elif [ "${shortname}" == "hw" ]; then fn_info_messages_hw elif [ "${shortname}" == "hz" ]; then fn_info_messages_hz + elif [ "${shortname}" == "hyt" ]; then + fn_info_messages_hyt elif [ "${shortname}" == "ins" ]; then fn_info_messages_ins elif [ "${shortname}" == "inss" ]; then @@ -1870,6 +1991,8 @@ fn_info_messages_select_engine() { fn_info_messages_jc3 elif [ "${shortname}" == "jk2" ]; then fn_info_messages_jk2 + elif [ "${shortname}" == "jk3" ]; then + fn_info_messages_jk3 elif [ "${shortname}" == "kf" ]; then fn_info_messages_kf elif [ "${shortname}" == "kf2" ]; then @@ -1914,6 +2037,10 @@ fn_info_messages_select_engine() { fn_info_messages_qw elif [ "${shortname}" == "ro" ]; then fn_info_messages_ro + elif [ "${shortname}" == "rsdw" ]; then + fn_info_messages_rsdw + elif [ "${shortname}" == "rwr" ]; then + fn_info_messages_rwr elif [ "${shortname}" == "rtcw" ]; then fn_info_messages_rtcw elif [ "${shortname}" == "samp" ]; then @@ -1922,7 +2049,7 @@ fn_info_messages_select_engine() { fn_info_messages_sb elif [ "${shortname}" == "sbots" ]; then fn_info_messages_sbots - elif [ "${shortname}" == "scpsl" ] || [ "${shortname}" == "scpslsm" ]; then + elif [ "${shortname}" == "scpsl" ]; then fn_info_messages_scpsl elif [ "${shortname}" == "sdtd" ]; then fn_info_messages_sdtd @@ -1956,6 +2083,10 @@ fn_info_messages_select_engine() { fn_info_messages_unt elif [ "${shortname}" == "vh" ]; then fn_info_messages_vh + elif [ "${shortname}" == "luanti" ]; then + fn_info_messages_luanti + elif [ "${shortname}" == "orar" ]; then + fn_info_messages_openra elif [ "${shortname}" == "vints" ]; then fn_info_messages_vints elif [ "${shortname}" == "rust" ]; then diff --git a/lgsm/modules/info_stats.sh b/lgsm/modules/info_stats.sh index c8a96552a0..927c85ae78 100755 --- a/lgsm/modules/info_stats.sh +++ b/lgsm/modules/info_stats.sh @@ -76,7 +76,10 @@ payload="{ \"memusedmbroundup\": \"${memusedmbroundup}\", \"ramused\": \"${memusedmbroundup}\", \"servercpu\": \"${cpumodel} ${cpucores} cores\", - \"servercpufreq\": \"${cpufreqency} x${cpucores}\", + \"servercpufreq\": \"${cpufreqency} x${cpulogicalcores}\", + \"servercpuphysicalcores\": \"${cpuphysicalcoresdisplay}\", + \"servercpulogicalcpus\": \"${cpulogicalcores}\", + \"servercpufreqrange\": \"${cpufrequencydisplay}\", \"serverdisk\": \"${totalspace}\", \"serverfilesdu\": \"${serverfilesdu}\", \"serverram\": \"${physmemtotal}\", @@ -129,6 +132,16 @@ if [ "${iftttalert}" == "on" ]; then fn_alert_payload curl -X POST "https://www.google-analytics.com/mp/collect?api_secret=${apisecret}&measurement_id=${measurementid}" -H "Content-Type: application/json" -d "${alertpayload}" fi +if [ "${matrixalert}" == "on" ]; then + alerttype="matrix" + fn_alert_payload + curl -X POST "https://www.google-analytics.com/mp/collect?api_secret=${apisecret}&measurement_id=${measurementid}" -H "Content-Type: application/json" -d "${alertpayload}" +fi +if [ "${ntfyalert}" == "on" ]; then + alerttype="ntfy" + fn_alert_payload + curl -X POST "https://www.google-analytics.com/mp/collect?api_secret=${apisecret}&measurement_id=${measurementid}" -H "Content-Type: application/json" -d "${alertpayload}" +fi if [ "${pushbulletalert}" == "on" ]; then alerttype="pushbullet" fn_alert_payload @@ -165,7 +178,7 @@ fn_script_log_info "* Game Server CPU Used: ${cpuusedmhzroundup}MHz" fn_script_log_info "* Game Server RAM Used: ${memusedmbroundup}MB" fn_script_log_info "* Game Server Disk Used: ${serverfilesdu}" fn_script_log_info "* Server CPU Model: ${cpumodel}" -fn_script_log_info "* Server CPU Frequency: ${cpufreqency}" +fn_script_log_info "* Server CPU Average Frequency: ${cpufreqency}" fn_script_log_info "* Server RAM: ${physmemtotal}" fn_script_log_info "* Server Disk: ${totalspace}" fn_script_log_info "* Virtual Environment: ${virtualenvironment}" diff --git a/lgsm/modules/install_config.sh b/lgsm/modules/install_config.sh index e25b8de5c7..4c3e34f124 100755 --- a/lgsm/modules/install_config.sh +++ b/lgsm/modules/install_config.sh @@ -256,7 +256,23 @@ fn_list_config_locations() { echo -e "Config documentation: ${italic}https://docs.linuxgsm.com/configuration${default}" } -if [ "${shortname}" == "sdtd" ]; then +if [ "${shortname}" == "luanti" ]; then + fn_check_cfgdir + if [ ! -e "${servercfgfullpath}" ] && [ ! -L "${servercfgfullpath}" ]; then + cp "${serverfiles}/${servercfgdefault}" "${servercfgfullpath}" + { + echo "server_name = LinuxGSM" + echo "name = admin" + echo "server_announce = false" + echo "bind_address = ${ip}" + echo "max_users = 20" + } >> "${servercfgfullpath}" + fi + fn_list_config_locations +elif [ "${shortname}" == "orar" ]; then + fn_check_cfgdir + fn_list_config_locations +elif [ "${shortname}" == "sdtd" ]; then fn_default_config_local fn_list_config_locations elif [ "${shortname}" == "ac" ]; then @@ -330,6 +346,11 @@ elif [ "${shortname}" == "bs" ]; then fn_default_config_remote fn_set_config_vars fn_list_config_locations +elif [ "${shortname}" == "bfe" ]; then + array_configs+=(config.json) + fn_default_config_remote + fn_set_config_vars + fn_list_config_locations elif [ "${shortname}" == "bb" ]; then array_configs+=(server.cfg) fn_default_config_remote @@ -482,6 +503,11 @@ elif [ "${shortname}" == "fctr" ]; then fn_default_config_remote fn_set_config_vars fn_list_config_locations +elif [ "${shortname}" == "fivem" ]; then + array_configs+=(server.cfg) + fn_default_config_remote + fn_set_config_vars + fn_list_config_locations elif [ "${shortname}" == "fof" ]; then array_configs+=(server.cfg) fn_default_config_remote @@ -492,7 +518,7 @@ elif [ "${shortname}" == "gmod" ]; then fn_default_config_remote fn_set_config_vars fn_list_config_locations -elif [ "${shortname}" == "hldm" ]; then +elif [ "${shortname}" == "hldm" ] || [ "${shortname}" == "hlwon" ] || [ "${shortname}" == "cswon" ]; then array_configs+=(server.cfg) fn_default_config_remote fn_set_config_vars @@ -520,6 +546,9 @@ elif [ "${shortname}" == "hl2dm" ]; then elif [ "${shortname}" == "hz" ]; then # Config is generated on first run : +elif [ "${shortname}" == "hyt" ]; then + # Config is generated on first run + : elif [ "${shortname}" == "ins" ]; then array_configs+=(server.cfg) fn_default_config_remote @@ -658,6 +687,11 @@ elif [ "${shortname}" == "jk2" ]; then array_configs+=(server.cfg) fn_default_config_remote fn_set_config_vars +elif [ "${shortname}" == "jk3" ]; then + array_configs+=(server.cfg) + fn_default_config_remote + fn_set_config_vars + fn_list_config_locations elif [ "${shortname}" == "qw" ]; then array_configs+=(server.cfg) fn_default_config_remote @@ -668,6 +702,11 @@ elif [ "${shortname}" == "ricochet" ]; then fn_default_config_remote fn_set_config_vars fn_list_config_locations +elif [ "${shortname}" == "rsdw" ]; then + array_configs+=(DedicatedServer.ini) + fn_default_config_remote + fn_set_config_vars + fn_list_config_locations elif [ "${shortname}" == "rtcw" ]; then array_configs+=(server.cfg) fn_default_config_remote @@ -677,7 +716,7 @@ elif [ "${shortname}" == "rust" ]; then array_configs+=(server.cfg) fn_default_config_remote fn_list_config_locations -elif [ "${shortname}" == "scpsl" ] || [ "${shortname}" == "scpslsm" ]; then +elif [ "${shortname}" == "scpsl" ]; then array_configs+=(config_gameplay.txt config_localadmin.txt) fn_default_config_remote fn_set_config_vars @@ -707,6 +746,9 @@ elif [ "${shortname}" == "squad" ]; then fn_default_config_remote fn_set_config_vars fn_list_config_locations +elif [ "${shortname}" == "rwr" ]; then + fn_default_config_local + fn_list_config_locations elif [ "${shortname}" == "sb" ]; then array_configs+=(starbound_server.config) fn_default_config_remote @@ -781,6 +823,11 @@ elif [ "${shortname}" == "ut2k4" ]; then fn_default_config_remote fn_set_config_vars fn_list_config_locations +elif [ "${shortname}" == "ut3" ]; then + array_configs+=(UTGame.ini UTWeb.ini UTEngine.ini) + fn_default_config_remote + fn_set_config_vars + fn_list_config_locations elif [ "${shortname}" == "ut99" ]; then array_configs+=(Default.ini) fn_default_config_remote diff --git a/lgsm/modules/install_eula.sh b/lgsm/modules/install_eula.sh index f32a1931e1..960d1fbc2b 100755 --- a/lgsm/modules/install_eula.sh +++ b/lgsm/modules/install_eula.sh @@ -11,6 +11,8 @@ if [ "${shortname}" == "ts3" ]; then eulaurl="https://www.teamspeak.com/en/privacy-and-terms" elif [ "${shortname}" == "mc" ] || [ "${shortname}" == "pmc" ]; then eulaurl="https://account.mojang.com/documents/minecraft_eula" +elif [ "${shortname}" == "scpsl" ]; then + eulaurl="https://link.scpslgame.com/eula" elif [ "${shortname}" == "ut" ]; then eulaurl="https://www.epicgames.com/unrealtournament/unreal-tournament-pre-alpha-test-development-build-eula" fi diff --git a/lgsm/modules/install_factorio_save.sh b/lgsm/modules/install_factorio_save.sh index 5dfb4758c1..ccaaa0615f 100755 --- a/lgsm/modules/install_factorio_save.sh +++ b/lgsm/modules/install_factorio_save.sh @@ -11,4 +11,6 @@ echo -e "" echo -e "${bold}${lightyellow}Creating initial Factorio savefile${default}" fn_messages_separator check_glibc.sh -"${executabledir}"/factorio --create "${serverfiles}/save1" +# Create the save in the saves directory so --start-server-load-latest can find it. +mkdir -p "${serverfiles}/saves" +"${executabledir}"/factorio --create "${serverfiles}/saves/save1" diff --git a/lgsm/modules/install_fivem_license.sh b/lgsm/modules/install_fivem_license.sh new file mode 100755 index 0000000000..9fa9db26f9 --- /dev/null +++ b/lgsm/modules/install_fivem_license.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# LinuxGSM install_fivem_license.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Explains how to set the FiveM server license key. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +echo -e "" +echo -e "${bold}${lightyellow}${gamename} License Key${default}" +fn_messages_separator +echo -e "A license key is required to run a ${gamename} server." +fn_script_log_info "A license key is required to run a ${gamename} server." + +echo -e "Get a free license key here:" +echo -e "${italic}https://portal.cfx.re/servers/registration-keys${default}" +fn_script_log_info "Get a free license key here:" +fn_script_log_info "https://portal.cfx.re/servers/registration-keys" +echo -e "" +fn_sleep_time_1 +echo -e "Set the license key with sv_licenseKey in ${servercfgfullpath}." +fn_script_log_info "Set the license key with sv_licenseKey in ${servercfgfullpath}." +echo -e "" diff --git a/lgsm/modules/install_gslt.sh b/lgsm/modules/install_gslt.sh index e4e4dbad72..58ecdd216e 100755 --- a/lgsm/modules/install_gslt.sh +++ b/lgsm/modules/install_gslt.sh @@ -17,6 +17,10 @@ else echo -e "GSLT is an optional feature for ${gamename} server." fn_script_log_info "GSLT is an optional feature for ${gamename} server" fi +if [ "${shortname}" == "csgo" ] && [ -n "${clientappid}" ]; then + echo -e "The GSLT must be created using the App ID set in clientappid (${clientappid})." + fn_script_log_info "The GSLT must be created using the App ID set in clientappid (${clientappid})" +fi echo -e "" echo -e "More info: ${italic}https://docs.linuxgsm.com/steamcmd/gslt${default}" diff --git a/lgsm/modules/install_logs.sh b/lgsm/modules/install_logs.sh index 9e1b89dbdf..987e7e8937 100755 --- a/lgsm/modules/install_logs.sh +++ b/lgsm/modules/install_logs.sh @@ -17,6 +17,7 @@ echo -en "creating log directory [ ${italic}${logdir}${default} ]" if [ ! -d "${logdir}" ]; then if ! mkdir -p "${logdir}"; then fn_print_fail_eol_nl + fn_script_log_fail "Creating log directory ${logdir}" core_exit.sh else fn_print_ok_eol_nl @@ -29,6 +30,7 @@ echo -en "creating script log directory [ ${italic}${lgsmlogdir}${default} ]" if [ ! -d "${lgsmlogdir}" ]; then if ! mkdir -p "${lgsmlogdir}"; then fn_print_fail_eol_nl + fn_script_log_fail "Creating script log directory ${lgsmlogdir}" core_exit.sh else fn_print_ok_eol_nl @@ -41,6 +43,7 @@ echo -en "creating script log [ ${italic}${lgsmlog}${default} ]" if [ ! -f "${lgsmlog}" ]; then if ! touch "${lgsmlog}"; then fn_print_fail_eol_nl + fn_script_log_fail "Creating script log ${lgsmlog}" core_exit.sh else fn_print_ok_eol_nl @@ -53,6 +56,7 @@ echo -en "creating console log directory [ ${italic}${consolelogdir}${default} ] if [ ! -d "${consolelogdir}" ]; then if ! mkdir -p "${consolelogdir}"; then fn_print_fail_eol_nl + fn_script_log_fail "Creating console log directory ${consolelogdir}" core_exit.sh else fn_print_ok_eol_nl @@ -65,6 +69,7 @@ echo -en "creating console log [ ${italic}${consolelog}${default} ]" if [ ! -f "${consolelog}" ]; then if ! touch "${consolelog}"; then fn_print_fail_eol_nl + fn_script_log_fail "Creating console log ${consolelog}" core_exit.sh else fn_print_ok_eol_nl @@ -78,6 +83,7 @@ if [ -n "${gamelogdir}" ]; then if [ ! -d "${gamelogdir}" ]; then if ! mkdir -p "${gamelogdir}"; then fn_print_fail_eol_nl + fn_script_log_fail "Creating game log directory ${gamelogdir}" core_exit.sh else fn_print_ok_eol_nl @@ -97,6 +103,7 @@ if [ -n "${gamelogdir}" ] && [ "${gamelogdir:0:${#logdir}}" != "${logdir}" ]; th if [ ! -h "${logdir}/server" ] || [ "$(readlink -f "${logdir}/server")" != "${gamelogdir}" ]; then if ! ln -nfs "${gamelogdir}" "${logdir}/server"; then fn_print_fail_eol_nl + fn_script_log_fail "Creating symlink to game log directory ${logdir}/server" core_exit.sh else fn_print_ok_eol_nl @@ -112,6 +119,7 @@ if [ -d "${HOME}/.steam/steam/logs" ]; then if [ ! -L "${logdir}/steam" ]; then if ! ln -nfs "${HOME}/.steam/steam/logs" "${logdir}/steam"; then fn_print_fail_eol_nl + fn_script_log_fail "Creating symlink to steam log directory ${logdir}/steam" core_exit.sh else fn_print_ok_eol_nl diff --git a/lgsm/modules/install_server_files.sh b/lgsm/modules/install_server_files.sh index e5f10739d2..966268e48d 100755 --- a/lgsm/modules/install_server_files.sh +++ b/lgsm/modules/install_server_files.sh @@ -9,198 +9,206 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_install_server_files() { if [ "${shortname}" == "ahl" ]; then - remote_fileurl="http://linuxgsm.download/ActionHalfLife/action_halflife-1.0.tar.xz" + remote_fileurl="https://linuxgsm.download/ActionHalfLife/ahl-1.0-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="action_halflife-1.0.tar.xz" + local_filename="ahl-1.0-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="61d7b79fd714888b6d65944fdaafa94a" + md5="4b502ed86fafd44b9b9dda99ee4cb44f" elif [ "${shortname}" == "bf1942" ]; then - remote_fileurl="http://linuxgsm.download/BattleField1942/bf1942_lnxded-1.61-hacked-to-1.612.full.tar.xz" + remote_fileurl="https://linuxgsm.download/BattleField1942/bf1942-1.612-linux-i386-linuxgsm-20261101.tar.xz" local_filedir="${tmpdir}" - local_filename="bf1942_lnxded-1.61-hacked-to-1.612.full.tar.xz" + local_filename="bf1942-1.612-linux-i386-linuxgsm-20261101.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="4223bf4ed85f5162c24b2cba51249b9e" + md5="0a3ae8721d3b14d81912b01fbfbd5cb2" elif [ "${shortname}" == "bfv" ]; then - remote_fileurl="http://linuxgsm.download/BattlefieldVietnam/bfv_linded-v1.21-20041207_patch.tar.xz" + remote_fileurl="https://linuxgsm.download/BattlefieldVietnam/bfv-1.21-linux-i386-linuxgsm-20261101.tar.xz" local_filedir="${tmpdir}" - local_filename="bfv_linded-v1.21-20041207_patch.tar.xz" + local_filename="bfv-1.21-linux-i386-linuxgsm-20261101.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="e3b4962cdd9d41e23c6fed65101bccde" + md5="532bc18529c7cb86fb41c79ec61c5283" elif [ "${shortname}" == "cod" ]; then - remote_fileurl="http://linuxgsm.download/CallOfDuty/cod-lnxded-1.5b-full.tar.xz" + remote_fileurl="https://linuxgsm.download/CallOfDuty/cod-1.5b-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="cod-lnxded-1.5-large.tar.xz" + local_filename="cod-1.5b-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="ee0ad1ccbfa1fd27fde01a4a431a5c2f" + md5="a588df9db95f64ce5b5065fd94995bc1" elif [ "${shortname}" == "coduo" ]; then - remote_fileurl="http://linuxgsm.download/CallOfDutyUnitedOffensive/coduo-lnxded-1.51b-full.tar.xz" + remote_fileurl="https://linuxgsm.download/CallOfDutyUnitedOffensive/coduo-1.51b-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="coduo-lnxded-1.51b-full.tar.xz" + local_filename="coduo-1.51b-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="35cabccd67adcda44aaebc59405915b9" + md5="deb2f9a66c9f3c7a23099c31c98242d0" elif [ "${shortname}" == "cod2" ]; then - remote_fileurl="http://linuxgsm.download/CallOfDuty2/cod2-lnxded-1.3-full.tar.xz" + remote_fileurl="https://linuxgsm.download/CallOfDuty2/cod2-1.3-linux-i386-linuxgsm-20261101.tar.xz" local_filedir="${tmpdir}" - local_filename="cod2-lnxded-1.3-full.tar.xz" + local_filename="cod2-1.3-linux-i386-linuxgsm-20261101.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="b8c4c611f01627dd43348e78478a3d41" + md5="e7dfaaf11f3f714c60e2ac1057476aa4" elif [ "${shortname}" == "cod4" ]; then - remote_fileurl="http://linuxgsm.download/CallOfDuty4/cod4x18_lnxded.tar.xz" + remote_fileurl="https://linuxgsm.download/CallOfDuty4/cod4x-21.2-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="cod4x18_lnxded.tar.xz" + local_filename="cod4x-21.2-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="d255b59b9756d7dbead67718208512ee" + md5="7c8d55d12e44f321f31ad1320567659a" elif [ "${shortname}" == "codwaw" ]; then - remote_fileurl="http://linuxgsm.download/CallOfDutyWorldAtWar/codwaw-lnxded-1.7-full.tar.xz" + remote_fileurl="https://linuxgsm.download/CallOfDutyWorldAtWar/codwaw-1.7-linux-i386-linuxgsm-20261101.tar.xz" local_filedir="${tmpdir}" - local_filename="codwaw-lnxded-1.7-full.tar.xz" + local_filename="codwaw-1.7-linux-i386-linuxgsm-20261101.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="2c6be1bb66ea631b9b2e7ae6216c6680" + md5="d7bdc6b2a671c3e07184e1a3262ec14c" + elif [ "${shortname}" == "cswon" ]; then + remote_fileurl="https://linuxgsm.download/CounterStrikeWON2/cswon-3111e-cs15-linux-i386-linuxgsm-20261104.tar.xz" + local_filedir="${tmpdir}" + local_filename="cswon-3111e-cs15-linux-i386-linuxgsm-20261104.tar.xz" + chmodx="nochmodx" + run="norun" + force="noforce" + md5="97f91d5a3b70ddff0fc9b2fd4ea1cfd6" + elif [ "${shortname}" == "hlwon" ]; then + remote_fileurl="https://linuxgsm.download/HalfLifeWON2/hlwon-3111e-linux-i386-linuxgsm-20261104.tar.xz" + local_filedir="${tmpdir}" + local_filename="hlwon-3111e-linux-i386-linuxgsm-20261104.tar.xz" + chmodx="nochmodx" + run="norun" + force="noforce" + md5="d4a57dc07648853138a700cacc84aef2" elif [ "${shortname}" == "mohaa" ]; then - remote_fileurl="http://linuxgsm.download/MedalofHonorAlliedAssault/moh_revival_v1.12_RC3.5.1.tar.xz" + remote_fileurl="https://linuxgsm.download/MedalofHonorAlliedAssault/mohaa-1.12-rc3.5.1-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="moh_revival_v1.12_RC3.5.1.tar.xz" + local_filename="mohaa-1.12-rc3.5.1-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="7c664538999252eeaf2b6d9949416480" + md5="bf66cbe1f4aefb221e17924e7bf9bdb4" elif [ "${shortname}" == "ns" ]; then - remote_fileurl="http://linuxgsm.download/NaturalSelection/ns_dedicated_server_v32.tar.xz" + remote_fileurl="https://linuxgsm.download/NaturalSelection/ns-3.2-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="ns_dedicated_server_v32.tar.xz" + local_filename="ns-3.2-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="23ec3cadd93d8bb1c475bad5b9cce370" + md5="a44d9769f9a035b98a4d57a7d7e1f81b" elif [ "${shortname}" == "q2" ]; then - remote_fileurl="http://linuxgsm.download/Quake2/quake2-3.20-glibc-i386-full-linux2.0.tar.xz" + remote_fileurl="https://linuxgsm.download/Quake2/q2-3.20-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="quake2-3.20-glibc-i386-full-linux2.0.tar.xz" + local_filename="q2-3.20-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="2908164a32d4808bb720f2161f6b0c82" + md5="f0abe39ed649765cd99b7e5e1c62b4f6" elif [ "${shortname}" == "q3" ]; then - remote_fileurl="http://linuxgsm.download/Quake3/quake3-1.32c-x86-full-linux.tar.xz" + remote_fileurl="https://linuxgsm.download/Quake3/q3-1.32c-linux-i386-linuxgsm-20261101.tar.xz" local_filedir="${tmpdir}" - local_filename="quake3-1.32c-x86-full-linux.tar.xz" + local_filename="q3-1.32c-linux-i386-linuxgsm-20261101.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="b0e26d8919fe9313fb9d8ded2360f3db" + md5="e6c958f4e01845d06bd5b8f3835bafa0" elif [ "${shortname}" == "q4" ]; then - remote_fileurl="http://linuxgsm.download/Quake4/quake4-1.4.2-x86-linuxded.tar.xz" - local_filedir="${tmpdir}" - local_filename="quake4-1.4.2-x86-linuxded.tar.xz" - chmodx="nochmodx" - run="norun" - force="noforce" - md5="afe30b44f23c8ae2ce6f0f464473d8ba" - elif [ "${shortname}" == "qw" ]; then - remote_fileurl="http://linuxgsm.download/QuakeWorld/nquake.server.linux.190506.full.tar.xz" + remote_fileurl="https://linuxgsm.download/Quake4/q4-1.4.2-linux-i386-linuxgsm-20261101.tar.xz" local_filedir="${tmpdir}" - local_filename="nquake.server.linux.190506.full.tar.xz" + local_filename="q4-1.4.2-linux-i386-linuxgsm-20261101.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="82055b7d973206c13a606db8ba288d03" + md5="7aaa88fb0ba0c533fe23b7b993fd6530" elif [ "${shortname}" == "rtcw" ]; then - remote_fileurl="http://linuxgsm.download/ReturnToCastleWolfenstein/iortcw-1.51c-x86_64-server-linux-20190507.tar.xz" + remote_fileurl="https://linuxgsm.download/ReturnToCastleWolfenstein/rtcw-iortcw-1.51c-linux-amd64-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="iortcw-1.51c-x86_64-server-linux-20190507.tar.xz" + local_filename="rtcw-iortcw-1.51c-linux-amd64-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="df6ff664d37dd0d22787848bdb3cac5f" + md5="6bb410ac0faf9048c2ca8f918b068ed0" elif [ "${shortname}" == "sfc" ]; then - remote_fileurl="http://linuxgsm.download/SourceFortsClassic/SFClassic-1.0-RC7-fix.tar.xz" + remote_fileurl="https://linuxgsm.download/SourceFortsClassic/sfc-1.0-rc7-fix-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="SFClassic-1.0-RC7-fix.tar.xz" + local_filename="sfc-1.0-rc7-fix-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="70077137185700e28fe6bbb6021d12bc" + md5="a0e3980e944cd321c5f064d752a7431e" elif [ "${shortname}" == "sof2" ]; then - remote_fileurl="http://linuxgsm.download/SoldierOfFortune2/sof2gold-1.03.tar.xz" + remote_fileurl="https://linuxgsm.download/SoldierOfFortune2/sof2-1.03-linux-i386-linuxgsm-20261101.tar.xz" local_filedir="${tmpdir}" - local_filename="sof2gold-1.03.tar.xz" + local_filename="sof2-1.03-linux-i386-linuxgsm-20261101.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="201e23bab04207d00ce813d001c483d9" + md5="d8cd9ad624290a1de1c72e43aa35195e" elif [ "${shortname}" == "ts" ]; then - remote_fileurl="http://linuxgsm.download/TheSpecialists/ts-3-linux-final.tar.xz" + remote_fileurl="https://linuxgsm.download/TheSpecialists/ts-3.0-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="ts-3-linux-final.tar.xz" + local_filename="ts-3.0-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="3c66ecff6e3644f7ac88015732a0fb93" + md5="4ff0fdc126ec09c07d6a6f915cb9145f" elif [ "${shortname}" == "ut2k4" ]; then - remote_fileurl="http://linuxgsm.download/UnrealTournament2004/ut2004-server-3369-3-ultimate-linux.tar.xz" + remote_fileurl="https://linuxgsm.download/UnrealTournament2004/ut2k4-3369.3-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="ut2004-server-3369-3-ultimate-linux.tar.xz" + local_filename="ut2k4-3369.3-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="9fceaab68554749f4b45be66613b9a15" + md5="f0ce6b3d3c7831e1a45e2a436a6aaa3b" elif [ "${shortname}" == "ut99" ]; then - remote_fileurl="http://linuxgsm.download/UnrealTournament99/ut99-server-469b-ultimate-linux.tar.xz" + remote_fileurl="https://linuxgsm.download/UnrealTournament99/ut99-469b-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="ut99-server-469b-ultimate-linux.tar.xz" + local_filename="ut99-469b-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="dba3f1122a5e60ee45ece7422fcf78f5" + md5="ccb9b0907f2f926204c911c3041df743" elif [ "${shortname}" == "ut" ]; then - remote_fileurl="http://linuxgsm.download/UnrealTournament/UnrealTournament-Server-XAN-3525360-Linux.tar.xz" + remote_fileurl="https://linuxgsm.download/UnrealTournament/ut-xan-3525360-linux-amd64-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="UnrealTournament-Server-XAN-3525360-Linux.tar.xz" + local_filename="ut-xan-3525360-linux-amd64-linuxgsm-20261102.tar.xz" chmodx="noexecute" run="norun" force="noforce" - md5="41dd92015713a78211eaccf503b72393" + md5="ffcb25dd03d82489e0cb3d6b9779e818" elif [ "${shortname}" == "ut3" ]; then - remote_fileurl="http://linuxgsm.download/UnrealTournament3/UT3-linux-server-2.1-openspy.tar.xz" + remote_fileurl="https://linuxgsm.download/UnrealTournament3/ut3-2.1-openspy-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="UT3-linux-server-2.1-openspy.tar.xz" + local_filename="ut3-2.1-openspy-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="f60b745613a8676666eb6a2450cbdc8e" + md5="a1ca829bd56d9a1abd17bf129e2bcb77" elif [ "${shortname}" == "vs" ]; then - remote_fileurl="http://linuxgsm.download/VampireSlayer/vs_l-6.0_full.tar.xz" + remote_fileurl="https://linuxgsm.download/VampireSlayer/vs-6.0-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="vs_l-6.0_full.tar.xz" + local_filename="vs-6.0-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="b322f79e0abd31847493c52acf802667" + md5="c1f908ab27772d8c6ca8ee731d32ddda" elif [ "${shortname}" == "wet" ]; then - remote_fileurl="http://linuxgsm.download/WolfensteinEnemyTerritory/enemy-territory.260b.tar.xz" + remote_fileurl="https://linuxgsm.download/WolfensteinEnemyTerritory/wet-2.60b-linux-i386-linuxgsm-20261101.tar.xz" local_filedir="${tmpdir}" - local_filename="enemy-territory.260b.tar.xz" + local_filename="wet-2.60b-linux-i386-linuxgsm-20261101.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="581a333cc7eacda2f56d5a00fe11eafa" + md5="60b7483c22db98effc3622dbb9e5710f" elif [ "${shortname}" == "samp" ]; then remote_fileurl="https://files.samp-sc.com/samp037svr_R2-1.tar.gz" local_filedir="${tmpdir}" @@ -210,23 +218,24 @@ fn_install_server_files() { force="noforce" md5="93705e165550c97484678236749198a4" elif [ "${shortname}" == "zmr" ]; then - remote_fileurl="http://linuxgsm.download/ZombieMasterReborn/zombie_master_reborn_b6_1.tar.xz" + remote_fileurl="https://linuxgsm.download/ZombieMasterReborn/zmr-b6.1-linux-i386-linuxgsm-20261102.tar.xz" local_filedir="${tmpdir}" - local_filename="zombie_master_reborn_b6_1.tar.xz" + local_filename="zmr-b6.1-linux-i386-linuxgsm-20261102.tar.xz" chmodx="nochmodx" run="norun" force="noforce" - md5="0188ae86dbc9376f11ae3032dba2d665" + md5="f451da013ed386d3081dfcfc390c7723" else fn_print_fail_nl "Installing ${gamename} Server failed, missing default configuration" fn_script_log_fail "Installing ${gamename} Server failed, missing default configuration" + core_exit.sh fi fn_fetch_file "${remote_fileurl}" "" "" "" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}" fn_dl_extract "${local_filedir}" "${local_filename}" "${serverfiles}" fn_clear_tmp } -if [ "${shortname}" == "mc" ] || [ "${shortname}" == "pmc" ] || [ "${shortname}" == "ut" ]; then +if [ "${shortname}" == "mc" ] || [ "${shortname}" == "pmc" ] || [ "${shortname}" == "scpsl" ] || [ "${shortname}" == "ut" ]; then install_eula.sh fi @@ -256,10 +265,22 @@ elif [ "${shortname}" == "mta" ]; then elif [ "${shortname}" == "fctr" ]; then update_fctr.sh install_factorio_save.sh +elif [ "${shortname}" == "fivem" ]; then + update_fivem.sh +elif [ "${shortname}" == "hyt" ]; then + update_hyt.sh elif [ "${shortname}" == "jk2" ]; then update_jk2.sh +elif [ "${shortname}" == "jk3" ]; then + update_jk3.sh +elif [ "${shortname}" == "luanti" ]; then + update_luanti.sh +elif [ "${shortname}" == "orar" ]; then + update_openra.sh elif [ "${shortname}" == "vints" ]; then update_vints.sh +elif [ "${shortname}" == "bfe" ]; then + update_bfe.sh elif [ "${shortname}" == "bb" ]; then update_bb.sh elif [ "${shortname}" == "ut99" ]; then @@ -267,6 +288,8 @@ elif [ "${shortname}" == "ut99" ]; then update_ut99.sh elif [ "${shortname}" == "xnt" ]; then update_xnt.sh +elif [ "${shortname}" == "qw" ]; then + update_qw.sh elif [ "${shortname}" == "etl" ]; then update_etl.sh elif [ -z "${appid}" ] || [ "${shortname}" == "ahl" ] || [ "${shortname}" == "q4" ] || [ "${shortname}" == "ns" ] || [ "${shortname}" == "sfc" ] || [ "${shortname}" == "ts" ] || [ "${shortname}" == "vs" ] || [ "${shortname}" == "zmr" ]; then diff --git a/lgsm/modules/mods_core.sh b/lgsm/modules/mods_core.sh index 3a14fcb84a..00c81a3439 100755 --- a/lgsm/modules/mods_core.sh +++ b/lgsm/modules/mods_core.sh @@ -29,17 +29,54 @@ fn_mod_install_files() { mkdir -p "${extractdest}" fi fn_dl_extract "${modstmpdir}" "${modfilename}" "${extractdest}" - # If modsubdirs names a specific subfolder, use its contents as the install root. + # If modsubdirs names a specific subfolder (or path to one), use its contents as the install root. if [ "${modsubdirs}" != "0" ] && [ -d "${extractdest}/${modsubdirs}" ]; then local tmpsubdir tmpsubdir=$(mktemp -d) mv "${extractdest}/${modsubdirs}" "${tmpsubdir}/" rm -rf "${extractdest}" - mv "${tmpsubdir}/${modsubdirs}" "${extractdest}" + mv "${tmpsubdir}/$(basename "${modsubdirs}")" "${extractdest}" rm -rf "${tmpsubdir}" fi } +# Compile a SourceMod plugin that is only distributed as source, using the installed SourceMod compiler. +# The compiled plugin is added to the extracted mod files so it is installed, updated and removed with the mod. +fn_mod_compile_sourcemod_plugin() { + local pluginname="${1}" + local spcompdir="${modinstalldir}/addons/sourcemod/scripting" + # Prefer the 64-bit compiler; the 32-bit spcomp needs i386 libraries. + local spcomp="${spcompdir}/spcomp64" + if [ ! -x "${spcomp}" ]; then + spcomp="${spcompdir}/spcomp" + fi + echo -en "compiling ${pluginname}.sp..." + fn_sleep_time + if [ ! -x "${spcomp}" ]; then + fn_print_fail_eol_nl + fn_script_log_fail "Compiling ${pluginname}.sp: SourceMod compiler not found in ${spcompdir}" + echo -e "* SourceMod compiler not found in ${spcompdir}" + exitcode=1 + core_exit.sh + fi + mkdir -p "${extractdest}/addons/sourcemod/plugins" + spcompoutput=$("${spcomp}" -i"${spcompdir}/include" "${extractdest}/addons/sourcemod/scripting/${pluginname}.sp" -o"${extractdest}/addons/sourcemod/plugins/${pluginname}.smx" 2>&1) + exitcode=$? + if [ "${exitcode}" -ne 0 ] || [ ! -s "${extractdest}/addons/sourcemod/plugins/${pluginname}.smx" ]; then + fn_print_fail_eol_nl + fn_script_log_fail "Compiling ${pluginname}.sp" + if [ -f "${lgsmlog}" ]; then + echo -e "${spcompoutput}" >> "${lgsmlog}" + fi + echo -e "${spcompoutput}" + exitcode=1 + core_exit.sh + else + fn_print_ok_eol_nl + fn_script_log_pass "Compiling ${pluginname}.sp" + fi +} + # Convert mod files to lowercase if needed. fn_mod_lowercase() { # Checking lowercase settings from mods array definition @@ -158,8 +195,20 @@ fn_mod_tidy_files_list() { sed -i "/^addons\/metamod\/sourcemod.vdf$/d" "${modsdir}/${modcommand}-files.txt" fi + # Keep Metamod:Source when removing CounterStrikeSharp, but remove its own VDF. + if [ "${modcommand}" == "counterstrikesharp" ]; then + sed -i "/^addons\/metamod$/d" "${modsdir}/${modcommand}-files.txt" + fi + + # Remove common CounterStrikeSharp paths from deletion list (Add your CounterStrikeSharp plugin here) + if [ "${modcommand}" == "matchzy" ]; then + sed -i "/^addons\/counterstrikesharp$/d" "${modsdir}/${modcommand}-files.txt" + sed -i "/^addons\/counterstrikesharp\/gamedata$/d" "${modsdir}/${modcommand}-files.txt" + sed -i "/^addons\/counterstrikesharp\/plugins$/d" "${modsdir}/${modcommand}-files.txt" + fi + # Remove common paths from deletion list (Add your sourcemod mod here) - if [ "${modcommand}" == "gokz" ] || [ "${modcommand}" == "ttt" ] || [ "${modcommand}" == "steamworks" ] || [ "${modcommand}" == "get5" ]; then + if [ "${modcommand}" == "gokz" ] || [ "${modcommand}" == "ttt" ] || [ "${modcommand}" == "steamworks" ] || [ "${modcommand}" == "get5" ] || [ "${modcommand}" == "nolobbyreservation" ]; then sed -i "/^addons\/sourcemod$/d" "${modsdir}/${modcommand}-files.txt" sed -i "/^addons\/sourcemod\/configs$/d" "${modsdir}/${modcommand}-files.txt" sed -i "/^addons\/sourcemod\/extensions$/d" "${modsdir}/${modcommand}-files.txt" @@ -197,6 +246,9 @@ fn_mod_tidy_files_list() { sed -i "/^addons\/sourcemod\/scripting\/include\/dhooks.inc$/d" "${modsdir}/${modcommand}-files.txt" sed -i "/^addons\/sourcemod\/scripting\/include\/updater.inc$/d" "${modsdir}/${modcommand}-files.txt" fi + if [ "${modcommand}" == "nolobbyreservation" ]; then + sed -i "/^addons\/sourcemod\/gamedata$/d" "${modsdir}/${modcommand}-files.txt" + fi } ## Information Gathering. @@ -693,6 +745,66 @@ fn_mod_remove_liblist_gam_file() { fi } +# modifiers for gameinfo.gi to add/remove the Metamod:Source search path +# Counter-Strike 2 only: the csgo paths below are specific to that game. +fn_mod_install_gameinfo_gi_file() { + local gameinfofile="${modinstalldir}/gameinfo.gi" + local metamodpattern='^[[:space:]]*"?Game"?[[:space:]]+"?csgo/addons/metamod"?[[:space:]]*(//.*)?$' + local lowviolencepattern='^[[:space:]]*"?Game_LowViolence"?[[:space:]]+"?csgo_lv"?[[:space:]]*(//.*)?$' + + if [ -f "${gameinfofile}" ]; then + # the search path survives a mod update, only add it when it is missing + if grep -Eq "${metamodpattern}" "${gameinfofile}"; then + fn_script_log_info "Metamod:Source search path already set in ${gameinfofile}" + else + # insert the search path below Game_LowViolence as documented by Metamod:Source + logentry="line (Game csgo/addons/metamod) inserted into ${gameinfofile}" + echo -en "adding Metamod:Source search path in gameinfo.gi..." + sed -i -E "\\@${lowviolencepattern}@a\\\\t\\t\\tGame\\tcsgo/addons/metamod" "${gameinfofile}" + grep -Eq "${metamodpattern}" "${gameinfofile}" + exitcode=$? + # if the insert didn't happen, error out + if [ "${exitcode}" -ne 0 ]; then + fn_script_log_fail "${logentry}" + fn_print_fail_eol_nl + core_exit.sh + else + fn_script_log_pass "${logentry}" + fn_print_ok_eol_nl + fi + fi + else + fn_script_log_fail "Unable to find ${gameinfofile}" + fn_print_fail_nl "Unable to find ${gameinfofile}" + core_exit.sh + fi +} + +# Unlike the install counterpart this does not call core_exit.sh on failure: +# command_mods_remove.sh ends with fn_script_log, which leaves exitcode alone, +# while command_mods_install.sh ends with fn_script_log_pass, which resets it to 0. +fn_mod_remove_gameinfo_gi_file() { + local gameinfofile="${modinstalldir}/gameinfo.gi" + local metamodpattern='^[[:space:]]*"?Game"?[[:space:]]+"?csgo/addons/metamod"?[[:space:]]*(//.*)?$' + + if [ -f "${gameinfofile}" ]; then + # is the search path found? If so remove it and keep the rest of the file + if grep -Eq "${metamodpattern}" "${gameinfofile}"; then + logentry="line (Game csgo/addons/metamod) removed from ${gameinfofile}" + echo -en "removing Metamod:Source search path in gameinfo.gi..." + # delete the line we inserted + sed -i -E "\\@${metamodpattern}@d" "${gameinfofile}" + if grep -Eq "${metamodpattern}" "${gameinfofile}"; then + fn_script_log_fail "${logentry}" + fn_print_fail_eol_nl + else + fn_script_log_pass "${logentry}" + fn_print_ok_eol_nl + fi + fi + fi +} + fn_mod_install_amxmodx_file() { # does plugins.ini exist? if [ -f "${modinstalldir}/addons/metamod/plugins.ini" ]; then diff --git a/lgsm/modules/mods_list.sh b/lgsm/modules/mods_list.sh index 39eca5e429..32ef44c024 100755 --- a/lgsm/modules/mods_list.sh +++ b/lgsm/modules/mods_list.sh @@ -18,57 +18,78 @@ metamodversion="1.21.1-am" metamodlatestfile="metamod-${metamodversion}.zip" metamoddownloadurl="https://www.amxmodx.org/release/${metamodlatestfile}" metamodurl="${metamoddownloadurl}" -# AMX Mod X: Base -amxxbaseversion="1.9.0-git5303" -amxxbasemod="base" -amxxbaselatestfile="amxmodx-${amxxbaseversion}-${amxxbasemod}-linux.tar.gz" -amxxbasedownloadurl="https://github.com/alliedmodders/amxmodx/releases/download/1.9.0.5303/${amxxbaselatestfile}" -amxxbaseurl="${amxxbasedownloadurl}" -# AMX Mod X: Counter-Strike -amxxcsversion="1.9.0-git5303" -amxxcsmod="cstrike" -amxxcslatestfile="amxmodx-${amxxbaseversion}-${amxxcsmod}-linux.tar.gz" -amxxcsdownloadurl="https://github.com/alliedmodders/amxmodx/releases/download/1.9.0.5303/${amxxcslatestfile}" -amxxcsurl="${amxxcsdownloadurl}" -# AMX Mod X: Day of Defeat -amxxdodversion="1.9.0-git5303" -amxxdodmod="dod" -amxxdodlatestfile="amxmodx-${amxxdodversion}-${amxxdodmod}-linux.tar.gz" -amxxdoddownloadurl="https://github.com/alliedmodders/amxmodx/releases/download/1.9.0.5303/${amxxdodlatestfile}" -amxxdodurl="${amxxdoddownloadurl}" -# AMX Mod X: Team Fortress Classic -amxxtfcversion="1.9.0-git5303" -amxxtfcmod="tfc" -amxxtfclatestfile="amxmodx-${amxxtfcversion}-${amxxtfcmod}-linux.tar.gz" -amxxtfcdownloadurl="https://github.com/alliedmodders/amxmodx/releases/download/1.9.0.5303/${amxxtfclatestfile}" -amxxtfcurl="${amxxtfcdownloadurl}" -# AMX Mod X: Natural Selection -amxxnsversion="1.9.0-git5303" -amxxnsmod="ns" -amxxnslatestfile="amxmodx-${amxxnsversion}-${amxxnsmod}-linux.tar.gz" -amxxnsdownloadurl="https://github.com/alliedmodders/amxmodx/releases/download/1.9.0.5303/${amxxnslatestfile}" -amxxnsurl="${amxxnsdownloadurl}" -# AMX Mod X: The Specialists -amxxtsversion="1.9.0-git5303" -amxxtsmod="ts" -amxxtslatestfile="amxmodx-${amxxtsversion}-${amxxtsmod}-linux.tar.gz" -amxxtsdownloadurl="https://github.com/alliedmodders/amxmodx/releases/download/1.9.0.5303/${amxxtslatestfile}" -amxxtsurl="${amxxtsdownloadurl}" +# AMX Mod X: Resolve one build for the base and all game addons on install/update only. +amxxbranch="1.10" +amxxdownloadbase="https://www.amxmodx.org/amxxdrop/${amxxbranch}" +amxxscrapeurl="${amxxdownloadbase}/amxmodx-latest-base-linux" +if { [ "${commandname}" == "MODS-INSTALL" ] || [ "${commandname}" == "MODS-UPDATE" ]; } \ + && { [ "${shortname}" == "cs" ] || [ "${shortname}" == "dod" ] || [ "${shortname}" == "tfc" ] || [ "${shortname}" == "ns" ] || [ "${shortname}" == "ts" ] || [ "${shortname}" == "hldm" ]; }; then + if ! amxxlatestfile=$(curl --connect-timeout 3 --max-time 30 --fail --silent --show-error --location "${amxxscrapeurl}"); then + fn_print_fail_nl "Unable to get the latest AMX Mod X ${amxxbranch} Linux build: ${amxxscrapeurl}" + fn_script_log_fail "Unable to get the latest AMX Mod X ${amxxbranch} Linux build: ${amxxscrapeurl}" + exitcode=1 + core_exit.sh + fi + if [[ ! "${amxxlatestfile}" =~ ^amxmodx-("${amxxbranch}"\.[0-9]+-git[0-9]+)-base-linux\.tar\.gz$ ]]; then + fn_print_fail_nl "Invalid AMX Mod X ${amxxbranch} Linux build filename: ${amxxscrapeurl}" + fn_script_log_fail "Invalid AMX Mod X ${amxxbranch} Linux build filename: ${amxxscrapeurl}" + exitcode=1 + core_exit.sh + fi + amxxversion="${BASH_REMATCH[1]}" + # AMX Mod X: Base + amxxbaselatestfile="amxmodx-${amxxversion}-base-linux.tar.gz" + amxxbaseurl="${amxxdownloadbase}/${amxxbaselatestfile}" + # AMX Mod X: Counter-Strike + amxxcslatestfile="amxmodx-${amxxversion}-cstrike-linux.tar.gz" + amxxcsurl="${amxxdownloadbase}/${amxxcslatestfile}" + # AMX Mod X: Day of Defeat + amxxdodlatestfile="amxmodx-${amxxversion}-dod-linux.tar.gz" + amxxdodurl="${amxxdownloadbase}/${amxxdodlatestfile}" + # AMX Mod X: Team Fortress Classic + amxxtfclatestfile="amxmodx-${amxxversion}-tfc-linux.tar.gz" + amxxtfcurl="${amxxdownloadbase}/${amxxtfclatestfile}" + # AMX Mod X: Natural Selection + amxxnslatestfile="amxmodx-${amxxversion}-ns-linux.tar.gz" + amxxnsurl="${amxxdownloadbase}/${amxxnslatestfile}" + # AMX Mod X: The Specialists + amxxtslatestfile="amxmodx-${amxxversion}-ts-linux.tar.gz" + amxxtsurl="${amxxdownloadbase}/${amxxtslatestfile}" +fi # Metamod:Source metamodsourceversion="1.12" metamodsourcescrapeurl="https://mms.alliedmods.net/mmsdrop/${metamodsourceversion}/mmsource-latest-linux" -metamodsourcelatestfile=$(wget "${metamodsourcescrapeurl}" -q -O -) +if [ "${engine}" == "source" ]; then + metamodsourcelatestfile=$(wget "${metamodsourcescrapeurl}" -q -O -) +fi metamodsourcedownloadurl="https://www.metamodsource.net/latest.php?os=linux&version=${metamodsourceversion}" metamodsourceurl="${metamodsourcedownloadurl}" +# Metamod:Source 2.0 +metamodsource2version="2.0" +metamodsource2scrapeurl="https://mms.alliedmods.net/mmsdrop/${metamodsource2version}/mmsource-latest-linux" +if [ "${shortname}" == "cs2" ]; then + metamodsource2latestfile=$(wget "${metamodsource2scrapeurl}" -q -O -) +fi +metamodsource2downloadurl="https://www.metamodsource.net/latest.php?os=linux&version=${metamodsource2version}" +metamodsource2url="${metamodsource2downloadurl}" # Sourcemod -sourcemodversion="1.13" +# Use the compatible stable SourceMod branch for Counter-Strike: Global Offensive. +if [ "${shortname}" == "csgo" ]; then + sourcemodversion="1.12" +else + sourcemodversion="1.13" +fi sourcemodscrapeurl="https://sm.alliedmods.net/smdrop/${sourcemodversion}/sourcemod-latest-linux" -sourcemodlatestfile=$(wget "${sourcemodscrapeurl}" -q -O -) +if [ "${engine}" == "source" ]; then + sourcemodlatestfile=$(wget "${sourcemodscrapeurl}" -q -O -) +fi sourcemoddownloadurl="https://www.sourcemod.net/latest.php?os=linux&version=${sourcemodversion}" sourcemodurl="${sourcemoddownloadurl}" # Steamworks steamworksscrapeurl="https://users.alliedmods.net/~kyles/builds/SteamWorks" -steamworkslatestfile=$(curl --connect-timeout 3 -sL ${steamworksscrapeurl} | grep -m 1 linux | cut -d '"' -f 4) +if [ "${shortname}" == "csgo" ]; then + steamworkslatestfile=$(curl --connect-timeout 3 -sL ${steamworksscrapeurl} | grep -m 1 linux | cut -d '"' -f 4) +fi steamworksdownloadurl="${steamworksscrapeurl}/${steamworkslatestfile}" steamworksurl="${steamworksdownloadurl}" # Stripper:Source @@ -77,35 +98,59 @@ stripperlatestfile="stripper-${stripperversion}-linux.tar.gz" stripperdownloadurl="http://www.bailopan.net/stripper/snapshots/1.2/${stripperlatestfile}" stripperurl="${stripperdownloadurl}" +# CS2 Mods +if [ "${shortname}" == "cs2" ]; then + counterstrikesharprelease=$(curl --connect-timeout 3 -sL https://api.github.com/repos/roflmuffin/CounterStrikeSharp/releases/latest) + counterstrikesharplastbuild=$(printf '%s\n' "${counterstrikesharprelease}" | jq '.assets[]? | select(.name | startswith("counterstrikesharp-with-runtime-linux-") and endswith(".zip"))' 2> /dev/null) + counterstrikesharplatestfile=$(printf '%s\n' "${counterstrikesharplastbuild}" | jq -r '.name') + counterstrikesharplatestlink=$(printf '%s\n' "${counterstrikesharplastbuild}" | jq -r '.browser_download_url') + # MatchZy: use the plugin-only archive, CounterStrikeSharp is installed as its own mod. + matchzyrelease=$(curl --connect-timeout 3 -sL https://api.github.com/repos/shobhit-pathak/MatchZy/releases/latest) + matchzylastbuild=$(printf '%s\n' "${matchzyrelease}" | jq '.assets[]? | select(.name | startswith("MatchZy-") and endswith(".zip") and (contains("with-cssharp") | not))' 2> /dev/null) + matchzylatestfile=$(printf '%s\n' "${matchzylastbuild}" | jq -r '.name') + matchzylatestlink=$(printf '%s\n' "${matchzylastbuild}" | jq -r '.browser_download_url') +fi + # CS:GO Mods -get5lastbuild=$(curl --connect-timeout 3 -sL https://api.github.com/repos/splewis/get5/releases/latest | jq '.assets[] |select(.browser_download_url | endswith(".tar.gz"))') -get5latestfile=$(echo -e "${get5lastbuild}" | jq -r '.name') -get5latestfilelink=$(echo -e "${get5lastbuild}" | jq -r '.browser_download_url') -csgopracticelatest=$(curl --connect-timeout 3 -sL https://api.github.com/repos/splewis/csgo-practice-mode/releases/latest | jq '.assets[]') -csgopracticelatestfile=$(echo -e "${csgopracticelatest}" | jq -r '.name') -csgopracticelatestlink=$(echo -e "${csgopracticelatest}" | jq -r '.browser_download_url') -csgopuglatest=$(curl --connect-timeout 3 -sL https://api.github.com/repos/splewis/csgo-pug-setup/releases/latest | jq '.assets[]') -csgopuglatestfile=$(echo -e "${csgopuglatest}" | jq -r '.name') -csgopuglatestlink=$(echo -e "${csgopuglatest}" | jq -r '.browser_download_url') -gokzlatestversion=$(curl --connect-timeout 3 -s https://api.github.com/repos/KZGlobalTeam/gokz/releases/latest | grep "tag_name" | cut -d : -f 2,3 | sed -E 's/.*"([^"]+)".*/\1/') -gokzlatestfile="GOKZ-v${gokzlatestversion}.zip" -gokzlatestlink="https://github.com/KZGlobalTeam/gokz/releases/download/${gokzlatestversion}/${gokzlatestfile}" -movementapilatestversion=$(curl --connect-timeout 3 -s https://api.github.com/repos/danzayau/MovementAPI/releases/latest | grep "tag_name" | cut -d : -f 2,3 | sed -E 's/.*"([^"]+)".*/\1/') -movementapilatestfile="MovementAPI-v${movementapilatestversion}.zip" -movementapilatestlink="https://github.com/danzayau/MovementAPI/releases/download/${movementapilatestversion}/${movementapilatestfile}" +if [ "${shortname}" == "csgo" ]; then + get5lastbuild=$(curl --connect-timeout 3 -sL https://api.github.com/repos/splewis/get5/releases/latest | jq '.assets[] |select(.browser_download_url | endswith(".tar.gz"))') + get5latestfile=$(echo -e "${get5lastbuild}" | jq -r '.name') + get5latestfilelink=$(echo -e "${get5lastbuild}" | jq -r '.browser_download_url') + csgopracticelatest=$(curl --connect-timeout 3 -sL https://api.github.com/repos/splewis/csgo-practice-mode/releases/latest | jq '.assets[]') + csgopracticelatestfile=$(echo -e "${csgopracticelatest}" | jq -r '.name') + csgopracticelatestlink=$(echo -e "${csgopracticelatest}" | jq -r '.browser_download_url') + csgopuglatest=$(curl --connect-timeout 3 -sL https://api.github.com/repos/splewis/csgo-pug-setup/releases/latest | jq '.assets[]') + csgopuglatestfile=$(echo -e "${csgopuglatest}" | jq -r '.name') + csgopuglatestlink=$(echo -e "${csgopuglatest}" | jq -r '.browser_download_url') + gokzlatestversion=$(curl --connect-timeout 3 -s https://api.github.com/repos/KZGlobalTeam/gokz/releases/latest | grep "tag_name" | cut -d : -f 2,3 | sed -E 's/.*"([^"]+)".*/\1/') + gokzlatestfile="GOKZ-v${gokzlatestversion}.zip" + gokzlatestlink="https://github.com/KZGlobalTeam/gokz/releases/download/${gokzlatestversion}/${gokzlatestfile}" + movementapilatestversion=$(curl --connect-timeout 3 -s https://api.github.com/repos/danzayau/MovementAPI/releases/latest | grep "tag_name" | cut -d : -f 2,3 | sed -E 's/.*"([^"]+)".*/\1/') + movementapilatestfile="MovementAPI-v${movementapilatestversion}.zip" + movementapilatestlink="https://github.com/danzayau/MovementAPI/releases/download/${movementapilatestversion}/${movementapilatestfile}" +fi # Rust carbonrustapilatestfile="Carbon.Linux.Release.tar.gz" -carbonrustlatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/CarbonCommunity/Carbon.Core/releases/tags/production_build | jq -r '.assets[]|select(.name == "Carbon.Linux.Release.tar.gz") | .browser_download_url') +if [ "${shortname}" == "rust" ]; then + carbonrustlatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/CarbonCommunity/Carbon.Core/releases/tags/production_build | jq -r '.assets[]|select(.name == "Carbon.Linux.Release.tar.gz") | .browser_download_url') +fi # Oxide -oxiderustlatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/OxideMod/Oxide.Rust/releases/latest | jq -r '.assets[]|select(.browser_download_url | contains("linux")) | .browser_download_url') -oxidehurtworldlatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/OxideMod/Oxide.Hurtworld/releases/latest | jq -r '.assets[].browser_download_url') -oxidesdtdlatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/OxideMod/Oxide.SevenDaysToDie/releases/latest | jq -r '.assets[]|select(.browser_download_url | contains("linux")) | .browser_download_url') -# Valheim Plus -valheimpluslatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/Grantapher/ValheimPlus/releases/latest | jq -r '.assets[]|select(.browser_download_url | contains("UnixServer.tar.gz")) | .browser_download_url') -# Valheim BepInEx -bepinexvhlatestlink=$(curl --connect-timeout 3 -sL "https://thunderstore.io/api/experimental/package/denikson/BepInExPack_Valheim/" -H "accept: application/json" | jq -r '.latest.download_url') +if [ "${shortname}" == "rust" ]; then + oxiderustlatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/OxideMod/Oxide.Rust/releases/latest | jq -r '.assets[]|select(.browser_download_url | contains("linux")) | .browser_download_url') +elif [ "${shortname}" == "hw" ]; then + oxidehurtworldlatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/OxideMod/Oxide.Hurtworld/releases/latest | jq -r '.assets[].browser_download_url') +elif [ "${shortname}" == "sdtd" ]; then + oxidesdtdlatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/OxideMod/Oxide.SevenDaysToDie/releases/latest | jq -r '.assets[]|select(.browser_download_url | contains("linux")) | .browser_download_url') +fi + +if [ "${shortname}" == "vh" ]; then + # Valheim Plus + valheimpluslatestlink=$(curl --connect-timeout 3 -sL https://api.github.com/repos/Grantapher/ValheimPlus/releases/latest | jq -r '.assets[]|select(.browser_download_url | contains("UnixServer.tar.gz")) | .browser_download_url') + # Valheim BepInEx + bepinexvhlatestlink=$(curl --connect-timeout 3 -sL "https://thunderstore.io/api/experimental/package/denikson/BepInExPack_Valheim/" -H "accept: application/json" | jq -r '.latest.download_url') +fi # Define mods information (required) @@ -122,7 +167,7 @@ modseparator="MOD" # [2] | "Pretty Name": the common name people use to call the mod that will be displayed to the user # [3] | "URL": link to the mod archive file; can be a variable previously defined while scraping a URL # [4] | "filename": the output filename -# [5] | "modsubdirs": name of a subfolder within the archive to extract as the install root (use "0" to extract all contents) +# [5] | "modsubdirs": name of (or path to) a subfolder within the archive to extract as the install root (use "0" to extract all contents) # [6] | "LowercaseOn/Off": LowercaseOff or LowercaseOn: enable/disable converting extracted files and directories to lowercase (some games require it) # [7] | "modinstalldir": the directory in which to install the mode (use LGSM dir variables such as ${systemdir}) # [8] | "/files/to/keep;", files & directories that should not be overwritten upon update, separated and ended with a semicolon; you can also use "OVERWRITE" value to ignore the value or "NOUPDATE" to disallow updating; for files to keep upon uninstall, see fn_mod_tidy_files_list from mods_core.sh @@ -157,7 +202,15 @@ mod_info_sourcemod=(MOD "sourcemod" "SourceMod" "${sourcemodurl}" "${sourcemodla mod_info_steamworks=(MOD "steamworks" "SteamWorks" "${steamworksurl}" "${steamworkslatestfile}" "0" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Counter-Strike: Global Offensive;" "NOTGAMES" "https://github.com/KyleSanderson/SteamWorks" "Exposing SteamWorks functions to SourcePawn") mod_info_stripper=(MOD "stripper" "Stripper Source" "${stripperurl}" "${stripperlatestfile}" "0" "LowercaseOff" "${systemdir}" "addons/stripper/maps;" "ENGINES" "Counter-Strike: Global Offensive;Counter-Strike: Source;Day of Defeat: Source;Half Life: Deathmatch;Half Life 2: Deathmatch;Insurgency;Left 4 Dead;Left 4 Dead 2;Nuclear Dawn;Team Fortress 2;" "NOTGAMES" "http://www.bailopan.net/stripper/" "Add or remove objects from map (requires MetaMod)") +# CS2 Mods +mod_info_metamodsource2=(MOD "metamodsource2" "Metamod:Source 2.0" "${metamodsource2url}" "${metamodsource2latestfile}" "0" "LowercaseOff" "${systemdir}" "addons/metamod/metaplugins.ini;" "ENGINES" "Counter-Strike 2;" "NOTGAMES" "https://www.metamodsource.net" "Plugins Framework (Dev Build)") +mod_info_counterstrikesharp=(MOD "counterstrikesharp" "CounterStrikeSharp" "${counterstrikesharplatestlink}" "${counterstrikesharplatestfile}" "0" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Counter-Strike 2;" "NOTGAMES" "https://docs.cssharp.dev/" "Write server plugins in C# (requires Metamod:Source 2.0)") +mod_info_matchzy=(MOD "matchzy" "MatchZy" "${matchzylatestlink}" "${matchzylatestfile}" "0" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Counter-Strike 2;" "NOTGAMES" "https://github.com/shobhit-pathak/MatchZy" "Plugin for practice, pugs, scrims and matches (requires CounterStrikeSharp)") + # CS:GO Mods +# NoLobbyReservation is pinned to a reviewed commit: it has no releases and is compiled from source on install. +nolobbyreservationcommit="003ab19fcf5e6eb67d21794218a4dc387d2923ca" +mod_info_nolobbyreservation=(MOD "nolobbyreservation" "NoLobbyReservation" "https://github.com/eldoradoel/NoLobbyReservation/archive/${nolobbyreservationcommit}.zip" "NoLobbyReservation-${nolobbyreservationcommit}.zip" "NoLobbyReservation-${nolobbyreservationcommit}/csgo" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Counter-Strike: Global Offensive;" "NOTGAMES" "https://github.com/eldoradoel/NoLobbyReservation" "Allows players to connect without a Steam lobby reservation - Required for standalone CS:GO clients to connect (requires SourceMod and MetaMod)") mod_info_gokz=(MOD "gokz" "GOKZ" "${gokzlatestlink}" "${gokzlatestfile}" "0" "LowercaseOff" "${systemdir}" "cfg;addons/sourcemod/configs;" "ENGINES" "Counter-Strike: Global Offensive;" "NOTGAMES" "https://github.com/KZGlobalTeam/gokz" "GOKZ ${gokzlatestversion} - Implements the KZ game mode (requires SourceMod and MetaMod)") mod_info_ttt=(MOD "ttt" "Trouble in Terrorist Town" "https://csgottt.com/downloads/ttt-latest-dev-${sourcemodversion}.zip" "ttt-latest.zip" "0" "LowercaseOff" "${systemdir}" "cfg;addons/sourcemod/configs;" "ENGINES" "Counter-Strike: Global Offensive;" "NOTGAMES" "https://github.com/Bara/TroubleinTerroristTown" "Implements the TTT game mode (requires SourceMod and MetaMod)") mod_info_get5=(MOD "get5" "Get 5" "${get5latestfilelink}" "${get5latestfile}" "0" "LowercaseOff" "${systemdir}" "cfg;addons/sourcemod/configs;" "ENGINES" "Counter-Strike: Global Offensive;" "NOTGAMES" "https://github.com/splewis/get5" "Plugin for competitive matches/scrims (requires SourceMod and MetaMod)") @@ -211,4 +264,4 @@ mod_info_valheimplus=(MOD "valheimplus" "Valheim PLUS" "${valheimpluslatestlink} mod_info_bepinexvh=(MOD "bepinexvh" "BepInEx Valheim" "${bepinexvhlatestlink}" "denikson-BepInExPack_Valheim.zip" "BepInExPack_Valheim" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Valheim;" "NOTGAMES" "https://valheim.thunderstore.io/package/denikson/BepInExPack_Valheim/" "Unity / XNA game patcher and plugin framework") # REQUIRED: Set all mods info into the global array -mods_global_array=("${mod_info_metamod[@]}" "${mod_info_base_amxx[@]}" "${mod_info_cs_amxx[@]}" "${mod_info_dod_amxx[@]}" "${mod_info_tfc_amxx[@]}" "${mod_info_ns_amxx[@]}" "${mod_info_ts_amxx[@]}" "${mod_info_metamodsource[@]}" "${mod_info_sourcemod[@]}" "${mod_info_steamworks[@]}" "${mod_info_gokz[@]}" "${mod_info_ttt[@]}" "${mod_info_get5[@]}" "${mod_info_prac[@]}" "${mod_info_pug[@]}" "${mod_info_dhook[@]}" "${mod_info_movement[@]}" "${mod_info_cleaner[@]}" "${mod_info_ulib[@]}" "${mod_info_ulx[@]}" "${mod_info_utime[@]}" "${mod_info_uclip[@]}" "${mod_info_acf[@]}" "${mod_info_acf_missiles[@]}" "${mod_info_acf_sweps[@]}" "${mod_info_advdupe2[@]}" "${mod_info_pac3[@]}" "${mod_info_wiremod[@]}" "${mod_info_wiremodextras[@]}" "${mod_info_darkrp[@]}" "${mod_info_darkrpmodification[@]}" "${mod_info_rustcarbon[@]}" "${mod_info_rustoxide[@]}" "${mod_info_hwoxide[@]}" "${mod_info_sdtdoxide[@]}" "${mod_info_advduplicator[@]}" "${mod_info_trackassemblytool[@]}" "${mod_info_physpropertiesadv[@]}" "${mod_info_controlsystemse2[@]}" "${mod_info_e2pistontiming[@]}" "${mod_info_propcannontool[@]}" "${mod_info_gearassemblytool[@]}" "${mod_info_spinnertool[@]}" "${mod_info_surfacefrictiontool[@]}" "${mod_info_magneticdipole[@]}" "${mod_info_environmentorganizer[@]}" "${mod_info_precision_alignment[@]}" "${mod_info_improved_stacker[@]}" "${mod_info_improved_weight[@]}" "${mod_info_improved_antinoclip[@]}" "${mod_info_laserstool[@]}" "${mod_info_valheimplus[@]}" "${mod_info_bepinexvh[@]}") +mods_global_array=("${mod_info_metamod[@]}" "${mod_info_base_amxx[@]}" "${mod_info_cs_amxx[@]}" "${mod_info_dod_amxx[@]}" "${mod_info_tfc_amxx[@]}" "${mod_info_ns_amxx[@]}" "${mod_info_ts_amxx[@]}" "${mod_info_metamodsource[@]}" "${mod_info_metamodsource2[@]}" "${mod_info_counterstrikesharp[@]}" "${mod_info_matchzy[@]}" "${mod_info_sourcemod[@]}" "${mod_info_nolobbyreservation[@]}" "${mod_info_steamworks[@]}" "${mod_info_gokz[@]}" "${mod_info_ttt[@]}" "${mod_info_get5[@]}" "${mod_info_prac[@]}" "${mod_info_pug[@]}" "${mod_info_dhook[@]}" "${mod_info_movement[@]}" "${mod_info_cleaner[@]}" "${mod_info_ulib[@]}" "${mod_info_ulx[@]}" "${mod_info_utime[@]}" "${mod_info_uclip[@]}" "${mod_info_acf[@]}" "${mod_info_acf_missiles[@]}" "${mod_info_acf_sweps[@]}" "${mod_info_advdupe2[@]}" "${mod_info_pac3[@]}" "${mod_info_wiremod[@]}" "${mod_info_wiremodextras[@]}" "${mod_info_darkrp[@]}" "${mod_info_darkrpmodification[@]}" "${mod_info_rustcarbon[@]}" "${mod_info_rustoxide[@]}" "${mod_info_hwoxide[@]}" "${mod_info_sdtdoxide[@]}" "${mod_info_advduplicator[@]}" "${mod_info_trackassemblytool[@]}" "${mod_info_physpropertiesadv[@]}" "${mod_info_controlsystemse2[@]}" "${mod_info_e2pistontiming[@]}" "${mod_info_propcannontool[@]}" "${mod_info_gearassemblytool[@]}" "${mod_info_spinnertool[@]}" "${mod_info_surfacefrictiontool[@]}" "${mod_info_magneticdipole[@]}" "${mod_info_environmentorganizer[@]}" "${mod_info_precision_alignment[@]}" "${mod_info_improved_stacker[@]}" "${mod_info_improved_weight[@]}" "${mod_info_improved_antinoclip[@]}" "${mod_info_laserstool[@]}" "${mod_info_valheimplus[@]}" "${mod_info_bepinexvh[@]}") diff --git a/lgsm/modules/query_gsquery.py b/lgsm/modules/query_gsquery.py old mode 100644 new mode 100755 index c4b8c3ddcf..35c46b10d5 --- a/lgsm/modules/query_gsquery.py +++ b/lgsm/modules/query_gsquery.py @@ -1,5 +1,4 @@ #! /usr/bin/env python3 -# -*- coding: utf-8 -*- # LinuxGSM query_gsquery.py module # Author: Daniel Gibbs # Contributors: https://linuxgsm.com/contrib @@ -14,6 +13,7 @@ engine_types = ( "protocol-valve", + "protocol-valve-won", "protocol-quake2", "protocol-quake3", "protocol-gamespy1", @@ -35,6 +35,7 @@ class GSQuery: default_buffer_length = 1024 sourcequery = ( "protocol-valve", + "protocol-valve-won", "avalanche3.0", "barotrauma", "madness", @@ -65,9 +66,12 @@ def __init__(self, arguments): """Create a query instance from parsed CLI args.""" self.argument = arguments - # if self.argument.engine in self.sourcequery: - self.query_prompt_string = b"\xff\xff\xff\xffTSource Engine Query\0" + self.query_prompt_string = ( + b"\xff\xff\xff\xffdetails\0" + if self.argument.engine == "protocol-valve-won" + else b"\xff\xff\xff\xffTSource Engine Query\0" + ) elif self.argument.engine in self.idtech2query: self.query_prompt_string = b"\xff\xff\xff\xffstatus\x00" elif self.argument.engine in self.idtech3query: @@ -135,12 +139,17 @@ def responding(self): # Receive. try: self.response = connection.recv(self.default_buffer_length) - except socket.error: + except OSError: self.fatal_error("Unable to receive", 2) connection.close() # Response. if self.response is None: self.fatal_error("No response", 3) + if self.argument.engine == "protocol-valve-won" and ( + not self.response.startswith(b"\xff\xff\xff\xffm") + or len(self.response.split(b"\0")) < 7 + ): + self.fatal_error("Invalid WON server response", 3) if len(self.response) < 5: sys.exit("Short response.", 3) else: diff --git a/lgsm/modules/update_bb.sh b/lgsm/modules/update_bb.sh old mode 100644 new mode 100755 index 1f2f12ce80..51b3f76d33 --- a/lgsm/modules/update_bb.sh +++ b/lgsm/modules/update_bb.sh @@ -9,7 +9,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to serverfiles. - fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "${remotebuildhash}" + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "${remotebuildhash}" fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}" echo "${remotebuild}" > "${serverfiles}/build.txt" fn_clear_tmp @@ -96,31 +96,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/update_bfe.sh b/lgsm/modules/update_bfe.sh new file mode 100755 index 0000000000..9c2ac8c895 --- /dev/null +++ b/lgsm/modules/update_bfe.sh @@ -0,0 +1,256 @@ +#!/bin/bash +# LinuxGSM update_bfe.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Handles updating of Battlefront Eternal servers. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +fn_update_node_remote() { + # Gets the latest Node.js 24 build and the installed version. + nodeurl="https://nodejs.org/dist/latest-v24.x" + nodeshasums=$(curl -s "${nodeurl}/SHASUMS256.txt") + nodefilename=$(echo "${nodeshasums}" | grep -o "node-v[0-9.]*-linux-${nodearch}.tar.xz" | head -1) + nodeversion=$(echo "${nodefilename}" | cut -d '-' -f 2) + nodehash=$(echo "${nodeshasums}" | grep " ${nodefilename}$" | awk '{print $1}') + if [ -z "${nodefilename}" ] || [ -z "${nodehash}" ]; then + fn_print_failure_nl "Unable to get Node.js build" + fn_script_log_fail "Unable to get Node.js build" + core_exit.sh + fi + nodelocalversion="" + if [ -x "${serverfiles}/node/bin/node" ]; then + nodelocalversion=$("${serverfiles}/node/bin/node" --version 2> /dev/null) + fi +} + +fn_update_node_dl() { + # Installs the Node.js runtime the server runs on. + fn_fetch_file "${nodeurl}/${nodefilename}" "" "" "" "${tmpdir}" "${nodefilename}" "nochmodx" "norun" "forcedl" "${nodehash}" + rm -rf "${serverfiles:?}/node.new" + fn_dl_extract "${tmpdir}" "${nodefilename}" "${serverfiles}/node.new" "${nodefilename%.tar.xz}" + rm -rf "${serverfiles:?}/node" + mv "${serverfiles}/node.new" "${serverfiles}/node" + fn_clear_tmp +} + +fn_update_node() { + fn_update_node_remote + if [ "${nodelocalversion}" != "${nodeversion}" ]; then + fn_update_node_dl + fi +} + +fn_update_node_compare() { + fn_print_dots "Checking for update: nodejs.org" + fn_update_node_remote + if [ "${nodelocalversion}" != "${nodeversion}" ]; then + date '+%s' > "${lockdir:?}/update.lock" + fn_print_ok_nl "Checking for update: nodejs.org" + fn_print "\n" + fn_print_nl "${bold}${underline}Node.js update${default} available" + fn_print_nl "* Local version: ${red}${nodelocalversion:-none}${default}" + fn_print_nl "* Remote version: ${green}${nodeversion}${default}" + fn_print "\n" + fn_script_log_info "Node.js update available" + fn_script_log_info "Local version: ${nodelocalversion:-none}" + fn_script_log_info "Remote version: ${nodeversion}" + previousbuild="Node.js ${nodelocalversion:-none}" + localbuild="Node.js ${nodelocalversion:-none}" + remotebuild="Node.js ${nodeversion}" + if [ "${commandname}" == "UPDATE" ]; then + unset updateonstart + fn_update_apply fn_update_node_dl + localbuild="${remotebuild}" + alert="update" + elif [ "${commandname}" == "CHECK-UPDATE" ]; then + alert="check-update" + fi + alert.sh + else + fn_print_ok_nl "Checking for update: nodejs.org" + fn_print "\n" + fn_print_nl "${bold}${underline}No Node.js update${default} available" + fn_print_nl "* Local version: ${green}${nodelocalversion}${default}" + fn_print_nl "* Remote version: ${green}${nodeversion}${default}" + fn_print "\n" + fn_script_log_info "No Node.js update available" + fn_script_log_info "Local version: ${nodelocalversion}" + fn_script_log_info "Remote version: ${nodeversion}" + fi +} + +fn_update_prepare() { + # Prepares the game data from the owned game when the release's tools change. + 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) + datakey=$(printf '%s' "${datakey}" | sha256sum | cut -c 1-32) + if [ -f "${serverfiles}/bfe-data/.lgsm-data-key" ] && [ "$(cat "${serverfiles}/bfe-data/.lgsm-data-key")" == "${datakey}" ]; then + return + fi + if [ ! -d "${serverfiles}/GameData" ]; then + fn_print_failure_nl "Game data not found: ${serverfiles}/GameData" + fn_script_log_fail "Game data not found: ${serverfiles}/GameData" + echo -e "* The Steam account must own STAR WARS Battlefront (Classic, 2004)." + echo -e "* Run ./${selfname} validate to download it." + core_exit.sh + fi + preparelog="${lgsmlogdir}/${selfname}-prepare.log" + echo -e "preparing game data, this can take several minutes" + fn_script_log_info "Preparing game data ${datakey}" + rm -rf "${serverfiles:?}/bfe-data.new" + mkdir -p "${serverfiles}/bfe-data.new" + ( + cd "${serverfiles}/bfe/tools" || exit 1 + 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 + ) + exitcode=$? + if [ "${exitcode}" -ne 0 ]; then + fn_print_failure_nl "Preparing game data" + fn_script_log_fail "Preparing game data, see ${preparelog}" + tail -n 20 "${preparelog}" + rm -rf "${serverfiles:?}/bfe-data.new" + core_exit.sh + fi + echo "${datakey}" > "${serverfiles}/bfe-data.new/.lgsm-data-key" + rm -rf "${serverfiles:?}/bfe-data" + mv "${serverfiles}/bfe-data.new" "${serverfiles}/bfe-data" + fn_print_ok_nl "Preparing game data" + fn_script_log_pass "Preparing game data" +} + +fn_update_dl() { + # Download and extract files to tmpdir. + fn_update_node + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "${remotebuildhash}" + rm -rf "${serverfiles:?}/bfe" + fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}/bfe" + fn_update_prepare + echo "${remotebuild}" > "${localbuildfile}" + fn_clear_tmp +} + +fn_update_localbuild() { + # Gets local build info. + fn_print_dots "Checking local build: ${remotelocation}" + if [ -f "${localbuildfile}" ]; then + localbuild="$(cat "${localbuildfile}")" + fi + if [ -z "${localbuild}" ]; then + fn_print_error "Checking local build: ${remotelocation}: missing local build info" + fn_script_log_error "Missing local build info" + fn_script_log_error "Set localbuild to 0" + localbuild="0" + else + fn_print_ok "Checking local build: ${remotelocation}" + fn_script_log_pass "Checking local build" + fi +} + +fn_update_remotebuild() { + # Gets remote build info. + apiurl="https://get.battlefronteternal.com/downloads/latest" + remotebuildresponse=$(curl -s "${apiurl}/SHA256SUMS") + remotebuildfilename=$(echo "${remotebuildresponse}" | grep -o "battlefront-eternal-server_[^ ]*_linux-${archivearch}\.tar\.xz" | head -1) + remotebuildhash=$(echo "${remotebuildresponse}" | grep " ${remotebuildfilename}$" | awk '{print $1}') + remotebuild=$(echo "${remotebuildfilename}" | cut -d '_' -f 2) + remotebuildurl="${apiurl}/${remotebuildfilename}" + if [ "${firstcommandname}" != "INSTALL" ]; then + fn_print_dots "Checking remote build: ${remotelocation}" + # Checks if remotebuild variable has been set. + if [ -z "${remotebuild}" ] || [ -z "${remotebuildhash}" ]; then + fn_print_fail "Checking remote build: ${remotelocation}" + fn_script_log_fail "Checking remote build" + core_exit.sh + else + fn_print_ok "Checking remote build: ${remotelocation}" + fn_script_log_pass "Checking remote build" + fi + else + # Checks if remotebuild variable has been set. + if [ -z "${remotebuild}" ] || [ -z "${remotebuildhash}" ]; then + fn_print_failure "Unable to get remote build" + fn_script_log_fail "Unable to get remote build" + core_exit.sh + fi + fi +} + +fn_update_compare() { + fn_print_dots "Checking for update: ${remotelocation}" + # Update has been found or force update. + if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then + # Create update lockfile. + date '+%s' > "${lockdir:?}/update.lock" + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}Update${default} available" + fn_print_nl "* Local build: ${red}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fn_print "\n" + fn_script_log_info "Update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + fn_script_log_info "${localbuild} > ${remotebuild}" + + if [ "${commandname}" == "UPDATE" ]; then + unset updateonstart + fn_update_apply fn_update_dl + alert="update" + elif [ "${commandname}" == "CHECK-UPDATE" ]; then + alert="check-update" + fi + alert.sh + else + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}No update${default} available" + fn_print_nl "* Local build: ${green}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + fn_print "\n" + fn_script_log_info "No update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fi +} + +if [ "$(uname -m)" == "aarch64" ]; then + archivearch="arm64" + nodearch="arm64" +else + archivearch="amd64" + nodearch="x64" +fi + +localbuildfile="${datadir}/${selfname}-bfe-version" +# The location where the builds are checked and downloaded. +remotelocation="get.battlefronteternal.com" + +if [ "${firstcommandname}" == "INSTALL" ]; then + fn_update_remotebuild + fn_update_dl +else + fn_print_dots "Checking for update" + fn_print_dots "Checking for update: ${remotelocation}" + fn_script_log_info "Checking for update: ${remotelocation}" + fn_update_localbuild + fn_update_remotebuild + fn_update_compare + if [ "${localbuild}" == "${remotebuild}" ] && [ "${forceupdate}" != "1" ]; then + fn_update_node_compare + fi +fi diff --git a/lgsm/modules/update_etl.sh b/lgsm/modules/update_etl.sh index 8486343e24..e44c058f8d 100755 --- a/lgsm/modules/update_etl.sh +++ b/lgsm/modules/update_etl.sh @@ -9,7 +9,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to serverfiles. - fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "${remotebuildhash}" + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "${remotebuildhash}" fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}" echo "${remotebuild}" > "${serverfiles}/build.txt" fn_clear_tmp @@ -98,31 +98,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/update_fctr.sh b/lgsm/modules/update_fctr.sh index 5de789cdb1..8b065738ea 100755 --- a/lgsm/modules/update_fctr.sh +++ b/lgsm/modules/update_fctr.sh @@ -9,7 +9,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to serverfiles. - fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "nohash" + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "nohash" fn_dl_extract "${tmpdir}" "factorio_headless_${factorioarch}-${remotebuild}.tar.xz" "${serverfiles}" "factorio" fn_clear_tmp } @@ -102,31 +102,15 @@ fn_update_compare() { if [ "${commandname}" == "UPDATE" ]; then # Keep track of the build before updating for alert purposes. previousbuild="${localbuild}" - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi # Refresh local build value after update (silent) so alerts show new version. diff --git a/lgsm/modules/update_fivem.sh b/lgsm/modules/update_fivem.sh new file mode 100755 index 0000000000..9557e3adee --- /dev/null +++ b/lgsm/modules/update_fivem.sh @@ -0,0 +1,139 @@ +#!/bin/bash +# LinuxGSM update_fivem.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Handles updating of FiveM servers. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +fn_update_resources() { + # Download and extract the cfx-server-data base resources. + fn_fetch_file "https://github.com/citizenfx/cfx-server-data/archive/refs/heads/master.tar.gz" "" "" "" "${tmpdir}" "cfx-server-data.tar.gz" "nochmodx" "norun" "force" "nohash" + fn_dl_extract "${tmpdir}" "cfx-server-data.tar.gz" "${serverfiles}" "cfx-server-data-master/resources" +} + +fn_update_dl() { + # Download and extract files to tmpdir. + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "nohash" + rm -rf "${serverfiles:?}/alpine" + fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}" + if [ ! -d "${serverfiles}/resources" ]; then + fn_update_resources + fi + echo "${remotebuild}" > "${localbuildfile}" + fn_clear_tmp +} + +fn_update_localbuild() { + # Gets local build info. + fn_print_dots "Checking local build: ${remotelocation}" + if [ -f "${localbuildfile}" ]; then + localbuild="$(cat "${localbuildfile}")" + fi + if [ -z "${localbuild}" ]; then + fn_print_error "Checking local build: ${remotelocation}: missing local build info" + fn_script_log_error "Missing local build info" + fn_script_log_error "Set localbuild to 0" + localbuild="0" + else + fn_print_ok "Checking local build: ${remotelocation}" + fn_script_log_pass "Checking local build" + fi +} + +fn_update_remotebuild() { + # Gets remote build info. + apiurl="https://changelogs-live.fivem.net/api/changelog/versions/linux/server" + remotebuildresponse=$(curl -s "${apiurl}") + remotebuild=$(echo "${remotebuildresponse}" | jq -r '.recommended') + remotebuildurl=$(echo "${remotebuildresponse}" | jq -r '.recommended_download') + remotebuildfilename="fx.tar.xz" + if [ "${firstcommandname}" != "INSTALL" ]; then + fn_print_dots "Checking remote build: ${remotelocation}" + # Checks if remotebuild variable has been set. + if [ -z "${remotebuild}" ] || [ "${remotebuild}" == "null" ] || [ -z "${remotebuildurl}" ] || [ "${remotebuildurl}" == "null" ]; then + fn_print_fail "Checking remote build: ${remotelocation}" + fn_script_log_fail "Checking remote build" + core_exit.sh + else + fn_print_ok "Checking remote build: ${remotelocation}" + fn_script_log_pass "Checking remote build" + fi + else + # Checks if remotebuild variable has been set. + if [ -z "${remotebuild}" ] || [ "${remotebuild}" == "null" ] || [ -z "${remotebuildurl}" ] || [ "${remotebuildurl}" == "null" ]; then + fn_print_failure "Unable to get remote build" + fn_script_log_fail "Unable to get remote build" + core_exit.sh + fi + fi +} + +fn_update_compare() { + fn_print_dots "Checking for update: ${remotelocation}" + # Update has been found or force update. + if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then + # Create update lockfile. + date '+%s' > "${lockdir:?}/update.lock" + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}Update${default} available" + fn_print_nl "* Local build: ${red}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fn_print "\n" + fn_script_log_info "Update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + fn_script_log_info "${localbuild} > ${remotebuild}" + + if [ "${commandname}" == "UPDATE" ]; then + unset updateonstart + fn_update_apply fn_update_dl + alert="update" + elif [ "${commandname}" == "CHECK-UPDATE" ]; then + alert="check-update" + fi + alert.sh + else + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}No update${default} available" + fn_print_nl "* Local build: ${green}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + fn_print "\n" + fn_script_log_info "No update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fi +} + +localbuildfile="${datadir}/${selfname}-fivem-version" +# The location where the builds are checked and downloaded. +remotelocation="runtime.fivem.net" + +if [ "${firstcommandname}" == "INSTALL" ]; then + fn_update_remotebuild + fn_update_dl +else + fn_print_dots "Checking for update" + fn_print_dots "Checking for update: ${remotelocation}" + fn_script_log_info "Checking for update: ${remotelocation}" + fn_update_localbuild + fn_update_remotebuild + fn_update_compare +fi diff --git a/lgsm/modules/update_hyt.sh b/lgsm/modules/update_hyt.sh new file mode 100755 index 0000000000..56b3700007 --- /dev/null +++ b/lgsm/modules/update_hyt.sh @@ -0,0 +1,292 @@ +#!/bin/bash +# LinuxGSM update_hyt.sh module +# Author: Andrew dos Santos +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Handles updating of Hytale servers. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +fn_update_hyt_downloader_arch() { + case "${arch}" in + x86_64 | amd64) + hytaledownloaderfile="hytale-downloader-linux-amd64" + ;; + aarch64 | arm64) + fn_print_failure "Hytale supports arm64 servers, but the official downloader archive currently used by LinuxGSM does not include a Linux arm64 downloader." + fn_script_log_fail "Unsupported Hytale downloader architecture: ${arch}" + core_exit.sh + ;; + *) + fn_print_failure "Unknown or unsupported hytale-downloader architecture: ${arch}" + fn_script_log_fail "Unknown or unsupported hytale-downloader architecture: ${arch}" + core_exit.sh + ;; + esac + hytaledownloader="${serverfiles}/${hytaledownloaderfile}" +} + +fn_update_downloader() { + fn_update_hyt_downloader_arch + if [ ! -f "${hytaledownloader}" ] || [ "${forceupdate}" == "1" ]; then + fn_fetch_file "https://downloader.hytale.com/hytale-downloader.zip" "" "" "" "${tmpdir}" "hytale-downloader.zip" "nochmodx" "norun" "forcedl" "nohash" + echo -en "extracting hytale-downloader..." + unzip -oq "${tmpdir}/hytale-downloader.zip" "${hytaledownloaderfile}" "QUICKSTART.md" -d "${serverfiles}" + exitcode=$? + if [ "${exitcode}" -ne 0 ]; then + fn_print_fail_eol_nl + fn_script_log_fail "Extracting hytale-downloader" + core_exit.sh + else + chmod +x "${hytaledownloader}" + fn_print_ok_eol_nl + fn_script_log_pass "Extracting hytale-downloader" + fi + fi +} + +fn_update_hyt_patchline_args() { + hytalepatchline="${hytalepatchline:-release}" + hytalepatchlineargs=() + if [ "${hytalepatchline}" != "release" ]; then + hytalepatchlineargs=(-patchline "${hytalepatchline}") + fi +} + +# The downloader needs a Hytale account login (OAuth device code) the first time it runs, and again +# if the saved credentials stop working. It waits for the login with no time limit, so it must +# never run unattended without credentials, otherwise cron jobs hang. +# Install always shows the login and waits: someone is watching, either in a terminal or in the +# container logs (e.g. docker logs) during the first install. +fn_update_hyt_auth() { + hytalecredentials="${serverfiles}/.hytale-downloader-credentials.json" + if [ "${firstcommandname}" == "INSTALL" ] || { [ -t 0 ] && [ -t 1 ]; }; then + hytaledownloadertimeout="900" + if [ ! -f "${hytalecredentials}" ]; then + echo -e "" + echo -e "${bold}${lightyellow}Hytale account login required${default}" + echo -e "The Hytale downloader needs you to log in with a Hytale account that owns the game." + echo -e "Open the URL shown below in a browser and approve the code within 15 minutes. This is only needed once." + echo -e "Running in Docker? The URL is also shown in the container logs (docker logs)." + echo -e "" + fn_script_log_info "Hytale downloader login required" + fi + else + hytaledownloadertimeout="300" + if [ ! -f "${hytalecredentials}" ]; then + fn_print_failure_nl "Hytale downloader is not logged in" + echo -e "* Run ./${selfname} update in a terminal and approve the Hytale account login once." + fn_script_log_fail "Hytale downloader is not logged in: ${hytalecredentials} not found" + core_exit.sh + fi + fi +} + +# Report a downloader timeout, which usually means it was waiting for a login. +fn_update_hyt_timeout_check() { + if [ "${exitcode}" -eq 124 ]; then + fn_print_failure_nl "Hytale downloader timed out, it is probably waiting for a Hytale account login" + echo -e "* The saved credentials may have expired. Run ./${selfname} update in a terminal to log in again." + fn_script_log_fail "Hytale downloader timed out after ${hytaledownloadertimeout}s" + core_exit.sh + fi +} + +fn_update_extract() { + extractdir="${tmpdir}/hytale-game" + rm -rf "${extractdir:?}" + mkdir -p "${extractdir}" + echo -en "extracting ${remotebuildfilename}..." + unzip -oq "${tmpdir}/${remotebuildfilename}" -d "${extractdir}" + exitcode=$? + if [ "${exitcode}" -ne 0 ]; then + fn_print_fail_eol_nl + fn_script_log_fail "Extracting ${remotebuildfilename}" + core_exit.sh + fi + + if [ -d "${extractdir}/game/Server" ]; then + extractedroot="${extractdir}/game" + else + extractedroot="${extractdir}" + fi + + mkdir -p "${serverfiles}" + if [ "${firstcommandname}" == "INSTALL" ]; then + cp -a "${extractedroot}/." "${serverfiles}/" + else + for item in "${extractedroot}"/*; do + [ -e "${item}" ] || continue + itemname="$(basename "${item}")" + case "${itemname}" in + Server | .hytale-downloader-credentials.json) + continue + ;; + jvm.options) + if [ -f "${serverfiles}/jvm.options" ]; then + continue + fi + ;; + esac + cp -a "${item}" "${serverfiles}/" + done + mkdir -p "${serverfiles}/Server" + for item in "${extractedroot}/Server"/*; do + [ -e "${item}" ] || continue + itemname="$(basename "${item}")" + case "${itemname}" in + backups | bans.json | config.json | logs | mods | permissions.json | universe | whitelist.json) + continue + ;; + esac + cp -a "${item}" "${serverfiles}/Server/" + done + fi + [ -f "${serverfiles}/start.sh" ] && chmod +x "${serverfiles}/start.sh" + fn_print_ok_eol_nl + fn_script_log_pass "Extracting ${remotebuildfilename}" + rm -rf "${extractdir:?}" +} + +fn_update_dl() { + fn_update_downloader + fn_update_hyt_patchline_args + remotebuildfilename="hytale-server-${remotebuild:-latest}.zip" + echo -e "downloading file [ ${italic}${remotebuildfilename}${default} ]" + fn_sleep_time + cd "${serverfiles}" || exit + fn_update_hyt_auth + timeout --foreground "${hytaledownloadertimeout}" "${hytaledownloader}" -download-path "${tmpdir}/${remotebuildfilename}" "${hytalepatchlineargs[@]}" -skip-update-check + exitcode=$? + fn_update_hyt_timeout_check + if [ "${exitcode}" -ne 0 ]; then + fn_print_failure_nl "Downloading ${remotebuildfilename}" + fn_script_log_fail "Downloading ${remotebuildfilename}" + core_exit.sh + fi + fn_update_extract + if [ -n "${remotebuild}" ]; then + echo "${remotebuild}" > "${localbuildfile}" + fi + fn_clear_tmp +} + +fn_update_hyt_check_localbuild_tracking() { + if [ -f "${localbuildfile}" ] && [ -f "${serverfiles}/Server/HytaleServer.jar" ] && [ "${serverfiles}/Server/HytaleServer.jar" -nt "${localbuildfile}" ]; then + fn_print_warn_nl "Hytale server files are newer than LinuxGSM build tracking" + echo -e "* Hytale may have updated itself outside LinuxGSM." + echo -e "* Run ./${selfname} update to refresh LinuxGSM version tracking." + fn_script_log_warn "Hytale server files are newer than LinuxGSM build tracking" + fi +} + +fn_update_localbuild() { + fn_print_dots "Checking local build: ${remotelocation}" + if [ -f "${localbuildfile}" ]; then + localbuild="$(cat "${localbuildfile}")" + fi + if [ -z "${localbuild}" ]; then + fn_print_error "Checking local build: ${remotelocation}: missing local build info" + fn_script_log_error "Missing local build info" + fn_script_log_error "Set localbuild to 0" + localbuild="0" + else + fn_print_ok "Checking local build: ${remotelocation}" + fn_script_log_pass "Checking local build" + fn_update_hyt_check_localbuild_tracking + fi +} + +fn_update_remotebuild() { + fn_update_downloader + fn_update_hyt_patchline_args + cd "${serverfiles}" || exit + remotebuildresponsefile="${tmpdir}/hytale-print-version-response.txt" + rm -f "${remotebuildresponsefile}" + fn_update_hyt_auth + timeout --foreground "${hytaledownloadertimeout}" "${hytaledownloader}" -print-version "${hytalepatchlineargs[@]}" -skip-update-check 2>&1 | tee "${remotebuildresponsefile}" + exitcode=${PIPESTATUS[0]} + fn_update_hyt_timeout_check + remotebuildresponse="$(cat "${remotebuildresponsefile}")" + if [ -f "${lgsmlog}" ]; then + cat "${remotebuildresponsefile}" >> "${lgsmlog}" + fi + remotebuild=$(echo "${remotebuildresponse}" | grep -Eo "[0-9]{4}\.[0-9]{2}\.[0-9]{2}-[A-Za-z0-9]+" | tail -1) + if [ -z "${remotebuild}" ]; then + remotebuild=$(echo "${remotebuildresponse}" | tail -1) + fi + + if [ "${firstcommandname}" != "INSTALL" ]; then + fn_print_dots "Checking remote build: ${remotelocation}" + if [ "${exitcode}" -ne 0 ] || [ -z "${remotebuild}" ] || [ "${remotebuild}" == "null" ]; then + fn_print_fail "Checking remote build: ${remotelocation}" + fn_script_log_fail "Checking remote build" + core_exit.sh + else + fn_print_ok "Checking remote build: ${remotelocation}" + fn_script_log_pass "Checking remote build" + fi + else + if [ "${exitcode}" -ne 0 ] || [ -z "${remotebuild}" ] || [ "${remotebuild}" == "null" ]; then + fn_print_failure "Unable to get remote build" + fn_script_log_fail "Unable to get remote build" + core_exit.sh + fi + fi +} + +fn_update_compare() { + fn_print_dots "Checking for update: ${remotelocation}" + if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then + date '+%s' > "${lockdir:?}/update.lock" + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}Update${default} available" + fn_print_nl "* Local build: ${red}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + fn_print_nl "* Patchline: ${hytalepatchline}" + fn_print "\n" + fn_script_log_info "Update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + fn_script_log_info "Patchline: ${hytalepatchline}" + + if [ "${commandname}" == "UPDATE" ]; then + unset updateonstart + fn_update_apply fn_update_dl + alert="update" + elif [ "${commandname}" == "CHECK-UPDATE" ]; then + alert="check-update" + fi + alert.sh + else + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}No update${default} available" + fn_print_nl "* Local build: ${green}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + fn_print_nl "* Patchline: ${hytalepatchline}" + fn_print "\n" + fn_script_log_info "No update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + fn_script_log_info "Patchline: ${hytalepatchline}" + fi +} + +info_distro.sh + +localbuildfile="${datadir}/${selfname}-hytale-version" +remotelocation="hytale.com" + +if [ "${firstcommandname}" == "INSTALL" ]; then + fn_update_remotebuild + fn_update_dl +else + fn_print_dots "Checking for update" + fn_print_dots "Checking for update: ${remotelocation}" + fn_script_log_info "Checking for update: ${remotelocation}" + fn_update_localbuild + fn_update_remotebuild + fn_update_compare +fi diff --git a/lgsm/modules/update_jk2.sh b/lgsm/modules/update_jk2.sh index ee40988d92..930f5ea98d 100755 --- a/lgsm/modules/update_jk2.sh +++ b/lgsm/modules/update_jk2.sh @@ -9,7 +9,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to serverfiles. - fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "nohash" + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "nohash" fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}/GameData" "linux-amd64" fn_clear_tmp } @@ -90,31 +90,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/update_jk3.sh b/lgsm/modules/update_jk3.sh new file mode 100755 index 0000000000..73da66b9d7 --- /dev/null +++ b/lgsm/modules/update_jk3.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# LinuxGSM update_jk3.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Handles updating of Jedi Academy OpenJK servers. + +# shellcheck disable=SC2034 # Used by the module loader. +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +fn_update_dl() { + # Download and extract files to GameData. + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "${remotebuildhash:-nohash}" + # OpenJK archives already have the executable and base/ at their root. + fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${systemdir}" + if [ ! -x "${executabledir}/openjkded.x86_64" ] || [ ! -f "${systemdir}/base/jampgamex86_64.so" ]; then + fn_print_fail_nl "OpenJK server files are missing after extraction" + fn_script_log_fail "OpenJK server files are missing after extraction" + # shellcheck disable=SC2034 # Used by core_exit.sh. + exitcode=1 + core_exit.sh + fi + if ! echo "${remotebuild}" > "${systemdir}/openjk-build.txt"; then + fn_print_fail_nl "Unable to save the OpenJK build ID" + fn_script_log_fail "Unable to save the OpenJK build ID" + # shellcheck disable=SC2034 # Used by core_exit.sh. + exitcode=1 + core_exit.sh + fi + fn_clear_tmp +} + +fn_update_localbuild() { + # Gets local build info. + fn_print_dots "Checking local build: ${remotelocation}" + # Uses build file to get local build. + localbuild=$(head -n 1 "${systemdir}/openjk-build.txt" 2> /dev/null) + if [ -z "${localbuild}" ]; then + fn_print_error "Checking local build: ${remotelocation}: missing local build info" + fn_script_log_error "Missing local build info" + fn_script_log_error "Set localbuild to 0" + localbuild="0" + else + fn_print_ok "Checking local build: ${remotelocation}" + fn_script_log_pass "Checking local build" + fi +} + +fn_update_remotebuild() { + # Gets remote build info. + apiurl="https://api.github.com/repos/JACoders/OpenJK/releases/latest" + remotebuildfilename="OpenJK-linux-x86_64.tar.gz" + remotebuildresponse=$(curl --connect-timeout 10 --max-time 30 --retry 2 --fail --silent --show-error --location "${apiurl}") || remotebuildresponse="" + # Select exactly one dedicated Linux x86_64 asset. + remotebuildasset=$(echo "${remotebuildresponse}" | jq -er --arg filename "${remotebuildfilename}" '[.assets[]? | select(.name == $filename)] | select(length == 1) | .[0] | select((.id | type) == "number" and (.browser_download_url | type) == "string")') || remotebuildasset="" + remotebuildurl=$(echo "${remotebuildasset}" | jq -r '.browser_download_url') + # The rolling latest tag is reused; replacing its asset changes the asset ID. + remotebuild=$(echo "${remotebuildasset}" | jq -r '.id') + remotebuildhash=$(echo "${remotebuildasset}" | jq -r '.digest // empty' | sed -n 's/^sha256://p') + + if [ "${firstcommandname}" != "INSTALL" ]; then + fn_print_dots "Checking remote build: ${remotelocation}" + fi + # Checks if the remote build and download URL have been set. + if [ -z "${remotebuild}" ] || [ "${remotebuild}" == "null" ] || [ -z "${remotebuildurl}" ] || [ "${remotebuildurl}" == "null" ]; then + if [ "${firstcommandname}" != "INSTALL" ]; then + fn_print_fail "Checking remote build: ${remotelocation}" + fn_script_log_fail "Checking remote build" + else + fn_print_fail_nl "Unable to get remote build" + fn_script_log_fail "Unable to get remote build" + fi + # shellcheck disable=SC2034 # Used by core_exit.sh. + exitcode=1 + core_exit.sh + elif [ "${firstcommandname}" != "INSTALL" ]; then + fn_print_ok "Checking remote build: ${remotelocation}" + fn_script_log_pass "Checking remote build" + fi +} + +fn_update_compare() { + fn_print_dots "Checking for update: ${remotelocation}" + # Update has been found or force update. + if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then + # Create update lockfile. + date '+%s' > "${lockdir:?}/update.lock" + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}Update${default} available" + fn_print_nl "* Local build: ${red}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -n "${branch}" ]; then + fn_print_nl "* Branch: ${branch}" + fi + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fn_print "\n" + fn_script_log_info "Update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -n "${branch}" ]; then + fn_script_log_info "Branch: ${branch}" + fi + fn_script_log_info "${localbuild} > ${remotebuild}" + + if [ "${commandname}" == "UPDATE" ]; then + unset updateonstart + fn_update_apply fn_update_dl + alert="update" + elif [ "${commandname}" == "CHECK-UPDATE" ]; then + alert="check-update" + fi + alert.sh + else + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}No update${default} available" + fn_print_nl "* Local build: ${green}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -n "${branch}" ]; then + fn_print_nl "* Branch: ${branch}" + fi + fn_print "\n" + fn_script_log_info "No update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -n "${branch}" ]; then + fn_script_log_info "Branch: ${branch}" + fi + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fi +} + +# The location where the builds are checked and downloaded. +remotelocation="github.com" + +if [ "${firstcommandname}" == "INSTALL" ]; then + fn_update_remotebuild + fn_update_dl +else + fn_print_dots "Checking for update" + fn_print_dots "Checking for update: ${remotelocation}" + fn_script_log_info "Checking for update: ${remotelocation}" + fn_update_localbuild + fn_update_remotebuild + fn_update_compare +fi diff --git a/lgsm/modules/update_luanti.sh b/lgsm/modules/update_luanti.sh new file mode 100755 index 0000000000..c80a146027 --- /dev/null +++ b/lgsm/modules/update_luanti.sh @@ -0,0 +1,162 @@ +#!/bin/bash +# LinuxGSM update_luanti.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Handles updating of Luanti servers. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +fn_update_dl() { + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "${remotebuildhash}" + fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}" "luanti" + if [ "${firstcommandname}" == "INSTALL" ] && [ ! -d "${serverfiles}/games/minetest" ]; then + fn_fetch_file "https://github.com/luanti-org/minetest_game/archive/refs/tags/5.8.0.tar.gz" "" "" "" "${tmpdir}" "minetest_game-5.8.0.tar.gz" "nochmodx" "norun" "force" "33a3bb43b08497a0bdb2f49f140a2829e582d5c16c0ad52be1595c803f706912" + mkdir -p "${serverfiles}/games/minetest" + fn_dl_extract "${tmpdir}" "minetest_game-5.8.0.tar.gz" "${serverfiles}/games/minetest" "minetest_game-5.8.0" + fi + fn_clear_tmp +} + +fn_update_localbuild() { + local mode="${1:-}" + if [ "${mode}" != "silent" ]; then + fn_print_dots "Checking local build: ${remotelocation}" + fi + localbuild=$("${executabledir}/${executable#./}" --version 2> /dev/null | awk '/^Luanti / {print $2; exit}') + localbuild="${localbuild:-0}" + if [ "${mode}" != "silent" ]; then + fn_print_ok "Checking local build: ${remotelocation}" + fi +} + +fn_update_remotebuild() { + case "$(uname -m)" in + x86_64) luantiarch="x86_64" ;; + aarch64) luantiarch="aarch64" ;; + *) + fn_print_fail_nl "Unsupported Luanti architecture: $(uname -m)" + fn_script_log_fail "Unsupported Luanti architecture: $(uname -m)" + core_exit.sh + ;; + esac + apiurl="https://api.github.com/repos/rollerozxa/luantiserver/releases/latest" + remotebuildresponse=$(curl -fsSL --retry 3 "${apiurl}") + remotebuild=$(echo "${remotebuildresponse}" | jq -r '.tag_name // empty') + remotebuildfilename="luantiserver-${remotebuild}-${luantiarch}.tar.gz" + remotebuildurl=$(echo "${remotebuildresponse}" | jq -r --arg name "${remotebuildfilename}" '.assets[]? | select(.name == $name) | .browser_download_url') + remotebuildhash=$(echo "${remotebuildresponse}" | jq -r --arg name "${remotebuildfilename}" '.assets[]? | select(.name == $name) | .digest // empty' | sed 's/^sha256://') + if [ -z "${remotebuild}" ] || [ -z "${remotebuildurl}" ] || [[ ! "${remotebuildhash}" =~ ^[0-9a-f]{64}$ ]]; then + fn_print_fail_nl "Unable to get Luanti release, download URL or SHA256 checksum" + fn_script_log_fail "Unable to get Luanti release, download URL or SHA256 checksum" + core_exit.sh + fi +} + +fn_update_compare() { + fn_print_dots "Checking for update: ${remotelocation}" + # Update has been found or force update. + if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then + # Create update lockfile. + date '+%s' > "${lockdir:?}/update.lock" + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}Update${default} available" + fn_print_nl "* Local build: ${red}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -n "${branch}" ]; then + fn_print_nl "* Branch: ${branch}" + fi + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fn_print "\n" + fn_script_log_info "Update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -n "${branch}" ]; then + fn_script_log_info "Branch: ${branch}" + fi + fn_script_log_info "${localbuild} > ${remotebuild}" + + if [ "${commandname}" == "UPDATE" ]; then + # Keep track of the build before updating for alert purposes. + previousbuild="${localbuild}" + unset updateonstart + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then + exitbypass=1 + command_start.sh + fn_firstcommand_reset + exitbypass=1 + fn_sleep_time_5 + command_stop.sh + fn_firstcommand_reset + fi + # Refresh local build value after update (silent) so alerts show new version. + fn_update_localbuild silent + # Verify the update applied correctly unless forced update to same version. + if [ "${localbuild}" != "${remotebuild}" ]; then + # If forced update and version unchanged treat as acceptable; otherwise failure. + if [ "${forceupdate}" != "1" ] || [ "${previousbuild}" = "${localbuild}" ]; then + fn_script_log_error "Update verification failed: expected ${remotebuild}, got ${localbuild}" + fn_print_fail_nl "Update verification failed: expected ${remotebuild}, got ${localbuild}" + updatefailureexpected="${remotebuild}" + updatefailuregot="${localbuild}" + alert="update-failed" + alert.sh + core_exit.sh + fi + else + fn_script_log_pass "Update verification success: ${previousbuild} -> ${localbuild}" + fi + unset exitbypass + alert="update" + elif [ "${commandname}" == "CHECK-UPDATE" ]; then + alert="check-update" + fi + alert.sh + else + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}No update${default} available" + fn_print_nl "* Local build: ${green}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -n "${branch}" ]; then + fn_print_nl "* Branch: ${branch}" + fi + fn_print "\n" + fn_script_log_info "No update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -n "${branch}" ]; then + fn_script_log_info "Branch: ${branch}" + fi + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fi +} + +# The location where the builds are checked and downloaded. +remotelocation="github.com/rollerozxa/luantiserver" + +if [ "${firstcommandname}" == "INSTALL" ]; then + fn_update_remotebuild + fn_update_dl +else + fn_print_dots "Checking for update" + fn_print_dots "Checking for update: ${remotelocation}" + fn_script_log_info "Checking for update: ${remotelocation}" + fn_update_localbuild + fn_update_remotebuild + fn_update_compare +fi diff --git a/lgsm/modules/update_mc.sh b/lgsm/modules/update_mc.sh index 81540f0020..1daf40bb97 100755 --- a/lgsm/modules/update_mc.sh +++ b/lgsm/modules/update_mc.sh @@ -105,31 +105,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/update_mcb.sh b/lgsm/modules/update_mcb.sh index 9940415a1c..1dec5ed99e 100755 --- a/lgsm/modules/update_mcb.sh +++ b/lgsm/modules/update_mcb.sh @@ -116,31 +116,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/update_mta.sh b/lgsm/modules/update_mta.sh index b1ba0459c8..353dca9d07 100755 --- a/lgsm/modules/update_mta.sh +++ b/lgsm/modules/update_mta.sh @@ -9,7 +9,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to tmpdir. - fn_fetch_file "http://linux.mtasa.com/dl/multitheftauto_linux_x64.tar.gz" "" "" "" "${tmpdir}" "multitheftauto_linux_x64.tar.gz" "nochmodx" "norun" "force" "nohash" + fn_fetch_file "https://linux.multitheftauto.com/dl/multitheftauto_linux_x64.tar.gz" "" "" "" "${tmpdir}" "multitheftauto_linux_x64.tar.gz" "nochmodx" "norun" "forcedl" "nohash" fn_dl_extract "${tmpdir}" "multitheftauto_linux_x64.tar.gz" "${serverfiles}" "multitheftauto_linux_x64" fn_clear_tmp } @@ -38,7 +38,7 @@ fn_update_remotebuild() { apiurl="https://linux.multitheftauto.com/revision/latest.txt" remotebuildresponse=$(curl -s "${apiurl}") remotebuildfilename="multitheftauto_linux_x64.tar.gz" - remotebuildurl="http://linux.mtasa.com/dl/multitheftauto_linux_x64.tar.gz" + remotebuildurl="https://linux.multitheftauto.com/dl/multitheftauto_linux_x64.tar.gz" remotebuild="${remotebuildresponse}" if [ "${firstcommandname}" != "INSTALL" ]; then fn_print_dots "Checking remote build: ${remotelocation}" @@ -98,31 +98,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass @@ -158,7 +142,7 @@ fn_update_compare() { } # The location where the builds are checked and downloaded. -remotelocation="linux.mtasa.com" +remotelocation="linux.multitheftauto.com" if [ "${firstcommandname}" == "INSTALL" ]; then fn_update_remotebuild diff --git a/lgsm/modules/update_openra.sh b/lgsm/modules/update_openra.sh new file mode 100755 index 0000000000..d5af00021f --- /dev/null +++ b/lgsm/modules/update_openra.sh @@ -0,0 +1,155 @@ +#!/bin/bash +# LinuxGSM update_openra.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Handles updating of OpenRA servers. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +fn_update_dl() { + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "chmodx" "norun" "force" "nohash" + local extractdir + extractdir=$(mktemp -d "${tmpdir}/openra.XXXXXX") || exit 1 + if ! (cd "${extractdir}" && "${tmpdir}/${remotebuildfilename}" --appimage-extract > /dev/null) || [ ! -x "${extractdir}/squashfs-root/usr/lib/openra/OpenRA.Server" ] || [ ! -x "${extractdir}/squashfs-root/AppRun" ]; then + fn_print_fail_nl "Extracting OpenRA server files" + fn_script_log_fail "Extracting OpenRA server files" + exitcode=1 + core_exit.sh + fi + printf '%s\n' "${remotebuild}" > "${extractdir}/squashfs-root/build.txt" || exit 1 + if [ -d "${serverfiles}/openra" ]; then + mv "${serverfiles}/openra" "${extractdir}/previous" || exit 1 + fi + if ! mv "${extractdir}/squashfs-root" "${serverfiles}/openra"; then + if [ -d "${extractdir}/previous" ]; then + mv "${extractdir}/previous" "${serverfiles}/openra" + fi + exitcode=1 + core_exit.sh + fi + fn_clear_tmp +} + +fn_update_localbuild() { + fn_print_dots "Checking local build: ${remotelocation}" + localbuild="0" + if [ -x "${serverfiles}/openra/AppRun" ] && [ -x "${serverfiles}/openra/usr/lib/openra/OpenRA.Server" ]; then + localbuild=$(head -n 1 "${serverfiles}/openra/build.txt" 2> /dev/null) + fi + if [ -z "${localbuild}" ]; then + fn_print_error "Checking local build: ${remotelocation}: missing local build info" + fn_script_log_error "Missing local build info" + localbuild="0" + else + fn_print_ok "Checking local build: ${remotelocation}" + fn_script_log_pass "Checking local build" + fi +} + +fn_update_remotebuild() { + if [ "$(uname -m)" != "x86_64" ]; then + fn_print_fail_nl "OpenRA requires an x86_64 Linux server" + fn_script_log_fail "OpenRA requires an x86_64 Linux server" + exitcode=1 + core_exit.sh + fi + apiurl="https://api.github.com/repos/OpenRA/OpenRA/releases/latest" + if ! remotebuildresponse=$(curl --fail --location --silent --show-error --connect-timeout 10 --max-time 60 "${apiurl}"); then + fn_print_fail_nl "Checking remote build: ${remotelocation}" + fn_script_log_fail "Checking remote build: ${apiurl}" + exitcode=1 + core_exit.sh + fi + remotebuildfilename="OpenRA-Red-Alert-x86_64.AppImage" + remotebuild=$(echo "${remotebuildresponse}" | jq -er '.tag_name | select(test("^release-[0-9]+$"))') + remotebuildurl=$(echo "${remotebuildresponse}" | jq -er --arg filename "${remotebuildfilename}" '[.assets[] | select(.name == $filename)] | select(length == 1) | .[0].browser_download_url') + if [ -z "${remotebuild}" ] || [[ "${remotebuildurl}" != https://github.com/OpenRA/OpenRA/releases/download/* ]]; then + fn_print_fail_nl "Unable to get OpenRA release asset" + fn_script_log_fail "Unable to get OpenRA release asset" + exitcode=1 + core_exit.sh + fi + fn_print_ok "Checking remote build: ${remotelocation}" + fn_script_log_pass "Checking remote build: ${remotebuild}" +} + +fn_update_compare() { + fn_print_dots "Checking for update: ${remotelocation}" + # Update has been found or force update. + if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then + # Create update lockfile. + date '+%s' > "${lockdir:?}/update.lock" + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}Update${default} available" + fn_print_nl "* Local build: ${red}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -n "${branch}" ]; then + fn_print_nl "* Branch: ${branch}" + fi + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fn_print "\n" + fn_script_log_info "Update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -n "${branch}" ]; then + fn_script_log_info "Branch: ${branch}" + fi + fn_script_log_info "${localbuild} > ${remotebuild}" + + if [ "${commandname}" == "UPDATE" ]; then + unset updateonstart + fn_update_apply fn_update_dl + unset exitbypass + alert="update" + elif [ "${commandname}" == "CHECK-UPDATE" ]; then + alert="check-update" + fi + alert.sh + else + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}No update${default} available" + fn_print_nl "* Local build: ${green}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -n "${branch}" ]; then + fn_print_nl "* Branch: ${branch}" + fi + fn_print "\n" + fn_script_log_info "No update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -n "${branch}" ]; then + fn_script_log_info "Branch: ${branch}" + fi + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fi +} + +# The location where the builds are checked and downloaded. +remotelocation="github.com/OpenRA/OpenRA" + +if [ "${firstcommandname}" == "INSTALL" ]; then + fn_update_remotebuild + fn_update_dl +else + fn_print_dots "Checking for update" + fn_print_dots "Checking for update: ${remotelocation}" + fn_script_log_info "Checking for update: ${remotelocation}" + fn_update_localbuild + fn_update_remotebuild + fn_update_compare +fi diff --git a/lgsm/modules/update_pmc.sh b/lgsm/modules/update_pmc.sh index 9273a567ab..a5185e6929 100755 --- a/lgsm/modules/update_pmc.sh +++ b/lgsm/modules/update_pmc.sh @@ -9,7 +9,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to serverfiles. - fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "chmodx" "norun" "force" "${remotebuildhash}" + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "chmodx" "norun" "forcedl" "${remotebuildhash}" cp -f "${tmpdir}/${remotebuildfilename}" "${serverfiles}/${executable#./}" echo "${remotebuild}" > "${serverfiles}/build.txt" fn_clear_tmp @@ -116,31 +116,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/update_qw.sh b/lgsm/modules/update_qw.sh new file mode 100755 index 0000000000..adcbfdc917 --- /dev/null +++ b/lgsm/modules/update_qw.sh @@ -0,0 +1,162 @@ +#!/bin/bash +# LinuxGSM update_qw.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Handles updating of QuakeWorld servers. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +fn_update_fail() { + fn_print_fail_nl "${1}" + fn_script_log_fail "${1}" + exitcode=1 + core_exit.sh +} + +fn_update_dl() { + # Verify and stage the complete bundle before changing serverfiles. + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "${remotebuildhash}" + local stagedir configfile relativefile + stagedir=$(mktemp -d "${tmpdir}/qw-update.XXXXXXXX") || fn_update_fail "Unable to create QuakeWorld staging directory" + fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${stagedir}" + if [ ! -x "${stagedir}/mvdsv" ] || [ ! -f "${stagedir}/ktx/qwprogs.so" ] || [ ! -f "${stagedir}/ktx/server.cfg" ]; then + fn_update_fail "Invalid QuakeWorld bundle layout" + fi + + # Keep existing configs, map lists and local scripts, including config symlinks. + # New default configs are still installed. Never remove files from serverfiles. + while IFS= read -r -d '' configfile; do + relativefile="${configfile#"${stagedir}/"}" + case "${relativefile,,}" in + *.cfg | *.conf | *.ini | *.txt | *.sh) ;; + *) + if [ "${serverfiles}/${relativefile}" != "${servercfgfullpath}" ]; then + continue + fi + ;; + esac + if [ -e "${serverfiles}/${relativefile}" ] || [ -L "${serverfiles}/${relativefile}" ]; then + rm -f "${configfile}" || fn_update_fail "Unable to preserve QuakeWorld config: ${relativefile}" + fi + done < <(find "${stagedir}" \( -type f -o -type l \) -print0) + + cp -a "${stagedir}/." "${serverfiles}/" || fn_update_fail "Unable to copy QuakeWorld update" + echo "${remotebuild}" > "${serverfiles}/build.txt" || fn_update_fail "Unable to save QuakeWorld build" + fn_clear_tmp +} + +fn_update_localbuild() { + # Gets local build info. + fn_print_dots "Checking local build: ${remotelocation}" + # Legacy installations without build.txt are updated once. + localbuild=$(head -n 1 "${serverfiles}/build.txt" 2> /dev/null) + if [ -z "${localbuild}" ]; then + fn_print_error "Checking local build: ${remotelocation}: missing local build info" + fn_script_log_error "Missing local build info" + fn_script_log_error "Set localbuild to 0" + localbuild="0" + else + fn_print_ok "Checking local build: ${remotelocation}" + fn_script_log_pass "Checking local build" + fi +} + +fn_update_remotebuild() { + # Use the dated release, not the mutable release tagged "latest". + apiurl="https://api.github.com/repos/GameServerManagers/qwserver-build/releases/latest" + fn_print_dots "Checking remote build: ${remotelocation}" + remotebuildresponse=$(curl -fsSL --connect-timeout 10 --max-time 60 "${apiurl}") || fn_update_fail "Unable to get QuakeWorld release" + remotebuild=$(echo "${remotebuildresponse}" | jq -er '.tag_name | select(test("^build-[0-9]{8}$"))') || fn_update_fail "Invalid QuakeWorld release tag" + remotebuildfilename="nquake.server.linux.${remotebuild#build-}.full.tar.xz" + remotebuildurl=$(echo "${remotebuildresponse}" | jq -er --arg name "${remotebuildfilename}" '[.assets[] | select(.name == $name)] | select(length == 1) | .[0].browser_download_url | select(type == "string" and startswith("https://"))') || fn_update_fail "Missing QuakeWorld release archive" + local checksumurl checksums + checksumurl=$(echo "${remotebuildresponse}" | jq -er '[.assets[] | select(.name == "SHA256SUMS")] | select(length == 1) | .[0].browser_download_url | select(type == "string" and startswith("https://"))') || fn_update_fail "Missing QuakeWorld checksums" + checksums=$(curl -fsSL --connect-timeout 10 --max-time 60 "${checksumurl}") || fn_update_fail "Unable to get QuakeWorld checksums" + remotebuildhash=$(echo "${checksums}" | awk -v filename="${remotebuildfilename}" 'NF == 2 && $2 == filename {print $1}') + if [[ ! "${remotebuildhash}" =~ ^[a-f0-9]{64}$ ]]; then + fn_update_fail "Missing or invalid QuakeWorld archive checksum" + fi + fn_print_ok "Checking remote build: ${remotelocation}" + fn_script_log_pass "Checking remote build" +} + +fn_update_compare() { + fn_print_dots "Checking for update: ${remotelocation}" + # Update has been found or force update. + if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then + # Create update lockfile. + date '+%s' > "${lockdir:?}/update.lock" + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}Update${default} available" + fn_print_nl "* Local build: ${red}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -n "${branch}" ]; then + fn_print_nl "* Branch: ${branch}" + fi + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fn_print "\n" + fn_script_log_info "Update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -n "${branch}" ]; then + fn_script_log_info "Branch: ${branch}" + fi + fn_script_log_info "${localbuild} > ${remotebuild}" + + if [ "${commandname}" == "UPDATE" ]; then + unset updateonstart + fn_update_apply fn_update_dl + unset exitbypass + alert="update" + elif [ "${commandname}" == "CHECK-UPDATE" ]; then + alert="check-update" + fi + alert.sh + else + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_print "\n" + fn_print_nl "${bold}${underline}No update${default} available" + fn_print_nl "* Local build: ${green}${localbuild}${default}" + fn_print_nl "* Remote build: ${green}${remotebuild}${default}" + if [ -n "${branch}" ]; then + fn_print_nl "* Branch: ${branch}" + fi + fn_print "\n" + fn_script_log_info "No update available" + fn_script_log_info "Local build: ${localbuild}" + fn_script_log_info "Remote build: ${remotebuild}" + if [ -n "${branch}" ]; then + fn_script_log_info "Branch: ${branch}" + fi + if [ -f "${rootdir}/.dev-debug" ]; then + fn_print_nl "Remote build info" + fn_print_nl "* apiurl: ${apiurl}" + fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" + fn_print_nl "* remotebuildurl: ${remotebuildurl}" + fn_print_nl "* remotebuild: ${remotebuild}" + fi + fi +} + +# The location where the builds are checked and downloaded. +remotelocation="github.com" + +if [ "${firstcommandname}" == "INSTALL" ]; then + fn_update_remotebuild + fn_update_dl +else + fn_print_dots "Checking for update" + fn_print_dots "Checking for update: ${remotelocation}" + fn_script_log_info "Checking for update: ${remotelocation}" + fn_update_localbuild + fn_update_remotebuild + fn_update_compare +fi diff --git a/lgsm/modules/update_steamcmd.sh b/lgsm/modules/update_steamcmd.sh index ccc8d6b368..dd2b9282ee 100755 --- a/lgsm/modules/update_steamcmd.sh +++ b/lgsm/modules/update_steamcmd.sh @@ -18,20 +18,12 @@ fn_print_dots "${remotelocation}" if [ "${forceupdate}" == "1" ]; then # forceupdate bypasses update checks. - if [ "${status}" != "0" ] && [ -v "${status}" ]; then - fn_print_restart_warning - exitbypass=1 - command_stop.sh - fn_firstcommand_reset - date '+%s' > "${lockdir:?}/update.lock" + if [ "${firstcommandname}" == "INSTALL" ]; then fn_dl_steamcmd - date +%s > "${lockdir}/last-updated.lock" - exitbypass=1 - command_start.sh - fn_firstcommand_reset + date +%s > "${lockdir:?}/last-updated.lock" else - fn_dl_steamcmd - date +%s > "${lockdir}/last-updated.lock" + date '+%s' > "${lockdir:?}/update.lock" + fn_update_apply fn_dl_steamcmd fi else fn_update_steamcmd_localbuild diff --git a/lgsm/modules/update_ts3.sh b/lgsm/modules/update_ts3.sh index ec3bc0060e..92136ed5d4 100755 --- a/lgsm/modules/update_ts3.sh +++ b/lgsm/modules/update_ts3.sh @@ -9,7 +9,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to serverfiles. - fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "${remotebuildhash}" + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "${remotebuildhash}" fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}" "teamspeak3-server_linux_${ts3arch}" fn_clear_tmp } @@ -97,31 +97,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/update_ut99.sh b/lgsm/modules/update_ut99.sh index 4e3f93b310..ce8158d05f 100755 --- a/lgsm/modules/update_ut99.sh +++ b/lgsm/modules/update_ut99.sh @@ -9,7 +9,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to serverfiles. - fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "nohash" + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "nohash" fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}" echo "${remotebuild}" > "${serverfiles}/build.txt" fn_clear_tmp @@ -34,15 +34,25 @@ fn_update_localbuild() { fn_update_remotebuild() { # Gets remote build info. apiurl="https://api.github.com/repos/OldUnreal/UnrealTournamentPatches/releases/latest" - remotebuildresponse=$(curl -s "${apiurl}") - remotebuildfilename=$(echo "${remotebuildresponse}" | jq -r '.assets[]|select(.browser_download_url | contains("Linux-amd64")) | .name') - remotebuildurl=$(echo "${remotebuildresponse}" | jq -r '.assets[]|select(.browser_download_url | contains("Linux-amd64")) | .browser_download_url') - remotebuild=$(echo "${remotebuildresponse}" | jq -r '.tag_name') + local attempt + for attempt in 1 2 3; do + remotebuildresponse=$(curl --connect-timeout 10 --max-time 30 --fail --silent --show-error --location "${apiurl}") || remotebuildresponse="" + remotebuild=$(echo "${remotebuildresponse}" | jq -er 'select((.tag_name | type) == "string" and (.tag_name | length) > 0) | .tag_name' 2> /dev/null) || remotebuild="" + remotebuildasset=$(echo "${remotebuildresponse}" | jq -cer '[.assets[]? | select((.browser_download_url | type) == "string" and (.browser_download_url | contains("Linux-amd64")))] | select(length == 1) | .[0]' 2> /dev/null) || remotebuildasset="" + remotebuildfilename=$(echo "${remotebuildasset}" | jq -er 'select((.name | type) == "string" and (.name | length) > 0) | .name' 2> /dev/null) || remotebuildfilename="" + remotebuildurl=$(echo "${remotebuildasset}" | jq -er 'select((.browser_download_url | type) == "string" and (.browser_download_url | length) > 0) | .browser_download_url' 2> /dev/null) || remotebuildurl="" + if [ -n "${remotebuild}" ] && [ -n "${remotebuildfilename}" ] && [ -n "${remotebuildurl}" ]; then + break + fi + if [ "${attempt}" -lt 3 ]; then + sleep 2 + fi + done if [ "${firstcommandname}" != "INSTALL" ]; then fn_print_dots "Checking remote build: ${remotelocation}" # Checks if remotebuild variable has been set. - if [ -z "${remotebuild}" ] || [ "${remotebuild}" == "null" ]; then + if [ -z "${remotebuild}" ] || [ -z "${remotebuildfilename}" ] || [ -z "${remotebuildurl}" ]; then fn_print_fail "Checking remote build: ${remotelocation}" fn_script_log_fail "Checking remote build" core_exit.sh @@ -52,7 +62,7 @@ fn_update_remotebuild() { fi else # Checks if remotebuild variable has been set. - if [ -z "${remotebuild}" ] || [ "${remotebuild}" == "null" ]; then + if [ -z "${remotebuild}" ] || [ -z "${remotebuildfilename}" ] || [ -z "${remotebuildurl}" ]; then fn_print_failure "Unable to get remote build" fn_script_log_fail "Unable to get remote build" core_exit.sh @@ -91,31 +101,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/update_vints.sh b/lgsm/modules/update_vints.sh index 5bf3df25d0..6f2da81ebd 100755 --- a/lgsm/modules/update_vints.sh +++ b/lgsm/modules/update_vints.sh @@ -9,7 +9,8 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to serverfiles. - fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "${remotebuildhash}" + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "${remotebuildhash}" + rm -rf "${serverfiles:?}/assets" fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}" fn_clear_tmp } @@ -101,31 +102,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/update_xnt.sh b/lgsm/modules/update_xnt.sh index e6f88cc274..751709e8bf 100755 --- a/lgsm/modules/update_xnt.sh +++ b/lgsm/modules/update_xnt.sh @@ -9,7 +9,7 @@ moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" fn_update_dl() { # Download and extract files to serverfiles. - fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "${remotebuildhash}" + fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "forcedl" "${remotebuildhash}" fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}" "Xonotic" fn_clear_tmp } @@ -111,31 +111,15 @@ fn_update_compare() { fn_script_log_info "${localbuild} > ${remotebuild}" if [ "${commandname}" == "UPDATE" ]; then - date +%s > "${lockdir:?}/last-updated.lock" unset updateonstart - check_status.sh - # If server stopped. - if [ "${status}" == "0" ]; then - fn_update_dl - if [ "${localbuild}" == "0" ]; then - exitbypass=1 - command_start.sh - fn_firstcommand_reset - exitbypass=1 - fn_sleep_time_5 - command_stop.sh - fn_firstcommand_reset - fi - # If server started. - else - fn_print_restart_warning + fn_update_apply fn_update_dl + if [ "${updatestatus}" == "0" ] && [ "${localbuild}" == "0" ]; then exitbypass=1 - command_stop.sh + command_start.sh fn_firstcommand_reset exitbypass=1 - fn_update_dl - exitbypass=1 - command_start.sh + fn_sleep_time_5 + command_stop.sh fn_firstcommand_reset fi unset exitbypass diff --git a/lgsm/modules/workshop_core.sh b/lgsm/modules/workshop_core.sh new file mode 100755 index 0000000000..e52265bddc --- /dev/null +++ b/lgsm/modules/workshop_core.sh @@ -0,0 +1,663 @@ +#!/bin/bash +# LinuxGSM workshop_core.sh module +# Author: Daniel Gibbs +# Contributors: https://linuxgsm.com/contrib +# Website: https://linuxgsm.com +# Description: Downloads and installs Steam Workshop mods for game servers that cannot download them. + +moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" + +# Installed mods are named ${workshopprefix} in the directory the game loads them from. +if [ "${shortname}" == "squad" ] || [ "${shortname}" == "squad44" ]; then + workshopdir="${systemdir}/Plugins/Mods" + workshopprefix="" +elif [ "${shortname}" == "ohd" ]; then + workshopdir="${systemdir}/Mods" + workshopprefix="" + workshopflatten=1 +elif [ "${shortname}" == "bt" ]; then + workshopdir="${serverfiles}/LocalMods" + workshopprefix="" +elif [ "${shortname}" == "hw" ]; then + workshopdir="${serverfiles}/steamapps/workshop/content/393420" + workshopprefix="" + workshopinplace=1 +elif [ "${shortname}" == "col" ]; then + workshopdir="${serverfiles}/gamedata/mods" + workshopprefix="" +elif [ "${shortname}" == "st" ]; then + workshopdir="${serverfiles}/mods" + workshopprefix="" +else + workshopdir="${serverfiles}/workshop" + workshopprefix="@" +fi +# Games that load mod files from their own directory get links to the installed files there. +if [ "${shortname}" == "sb" ]; then + workshoplinkdir="${serverfiles}/mods" +elif [ "${shortname}" == "l4d2" ]; then + workshoplinkdir="${serverfiles}/left4dead2/addons" +elif [ "${shortname}" == "sol" ]; then + workshoplinkdir="${serverfiles}" +fi +workshopdldir="${tmpdir}/workshop" +workshopmodlist="${datadir}/${selfname}-workshop.txt" +workshopapi="https://api.steampowered.com/ISteamRemoteStorage" +workshopapimax="100" +workshopretries="5" + +# Converts workshopmods into an ordered list of IDs. Accepts space, comma or semicolon separators. +fn_workshop_config_ids() { + workshopconfigids=() + local id + for id in ${workshopmods//[,;]/ }; do + if [[ "${id}" =~ ^[0-9]+$ ]]; then + workshopconfigids+=("${id}") + else + fn_print_warn_nl "Ignoring invalid Workshop ID: ${id}" + fn_script_log_warn "Ignoring invalid Workshop ID: ${id}" + fi + done +} + +# Queries the Steam Web API. Usage: fn_workshop_api ... +fn_workshop_api() { + local method="$1" + shift + local countparam="itemcount" + if [ "${method}" == "GetCollectionDetails" ]; then + countparam="collectioncount" + fi + local postdata=("--data-urlencode" "${countparam}=$#") + local index=0 + local id + for id in "$@"; do + postdata+=("--data-urlencode" "publishedfileids[${index}]=${id}") + index=$((index + 1)) + done + curl -sSL --connect-timeout 10 --max-time 60 "${postdata[@]}" "${workshopapi}/${method}/v1/" +} + +# Records which IDs are collections and their children, in batches. +fn_workshop_get_collections() { + local ids=("$@") + local start response + for ((start = 0; start < ${#ids[@]}; start += workshopapimax)); do + if ! response="$(fn_workshop_api GetCollectionDetails "${ids[@]:start:workshopapimax}")" || ! jq -e '.response' <<< "${response}" > /dev/null 2>&1; then + fn_print_fail_nl "Checking for update: ${remotelocation}: Unable to get collection details from Steam" + fn_script_log_fail "Checking for update: ${remotelocation}: Unable to get collection details from Steam" + core_exit.sh + fi + local id result children + while IFS=$'\t' read -r id result children; do + workshopchecked["${id}"]=1 + if [ "${result}" == "1" ]; then + workshopchildren["${id}"]="${children}" + fi + done < <(jq -r '.response.collectiondetails[] | [.publishedfileid, (.result | tostring), ([.children[]? | "\(.publishedfileid):\(.filetype)"] | join(" "))] | @tsv' <<< "${response}") + done +} + +# Adds an ID to workshopitems, expanding collections in their sort order. +fn_workshop_expand() { + local id="$1" + local depth="$2" + if [ -n "${workshopseen[${id}]}" ]; then + return + fi + workshopseen["${id}"]=1 + if [ -n "${workshopchildren[${id}]+set}" ]; then + if [ "${depth}" -gt 3 ]; then + fn_print_warn_nl "Skipping Workshop collection ${id}: collections are nested too deeply" + fn_script_log_warn "Skipping Workshop collection ${id}: collections are nested too deeply" + return + fi + local child + for child in ${workshopchildren[${id}]}; do + fn_workshop_expand "${child%%:*}" $((depth + 1)) + done + else + workshopitems+=("${id}") + fi +} + +# Builds workshopitems: the ordered list of Workshop items to install, with collections expanded. +fn_workshop_resolve() { + declare -gA workshopchecked=() + declare -gA workshopchildren=() + declare -gA workshopseen=() + workshopitems=() + fn_workshop_config_ids + if [ "${#workshopconfigids[@]}" -eq 0 ]; then + return + fi + local tocheck=("${workshopconfigids[@]}") + local round id child + for ((round = 0; round < 4 && ${#tocheck[@]} > 0; round++)); do + fn_workshop_get_collections "${tocheck[@]}" + local nested=() + for id in "${tocheck[@]}"; do + for child in ${workshopchildren[${id}]}; do + if [ "${child##*:}" == "2" ] && [ -z "${workshopchecked[${child%%:*}]}" ]; then + nested+=("${child%%:*}") + fi + done + done + tocheck=("${nested[@]}") + done + for id in "${workshopconfigids[@]}"; do + fn_workshop_expand "${id}" 0 + done +} + +# Gets title, game appid and last updated time for each item in workshopitems. +fn_workshop_get_details() { + declare -gA workshoptitle=() + declare -gA workshopappid=() + declare -gA workshoptimeupdated=() + local validitems=() + local start response + for ((start = 0; start < ${#workshopitems[@]}; start += workshopapimax)); do + if ! response="$(fn_workshop_api GetPublishedFileDetails "${workshopitems[@]:start:workshopapimax}")" || ! jq -e '.response' <<< "${response}" > /dev/null 2>&1; then + fn_print_fail_nl "Checking for update: ${remotelocation}: Unable to get Workshop item details from Steam" + fn_script_log_fail "Checking for update: ${remotelocation}: Unable to get Workshop item details from Steam" + core_exit.sh + fi + local id result appid timeupdated title + while IFS=$'\t' read -r id result appid timeupdated title; do + if [ "${result}" != "1" ] || [ -z "${timeupdated}" ]; then + fn_print_warn_nl "Skipping Workshop item ${id}: not found, or not public" + fn_script_log_warn "Skipping Workshop item ${id}: not found, or not public" + continue + fi + workshoptitle["${id}"]="${title}" + workshopappid["${id}"]="${appid}" + workshoptimeupdated["${id}"]="${timeupdated}" + done < <(jq -r '.response.publishedfiledetails[] | [.publishedfileid, (.result | tostring), (.consumer_app_id // "" | tostring), (.time_updated // "" | tostring), (.title // "" | gsub("[\t\n\r]"; " "))] | @tsv' <<< "${response}") + done + local item + for item in "${workshopitems[@]}"; do + if [ -n "${workshoptimeupdated[${item}]}" ]; then + validitems+=("${item}") + fi + done + workshopitems=("${validitems[@]}") +} + +# Prints the directory a Workshop item is installed in, if it is installed. +fn_workshop_moddir() { + local statefile + if [ -f "${workshopdir}/${workshopprefix}${1}/.lgsm-workshop" ]; then + echo "${workshopdir}/${workshopprefix}${1}" + return + fi + for statefile in "${workshopdir}"/*/.lgsm-workshop; do + if [ -f "${statefile}" ] && grep -qx "id=${1}" "${statefile}"; then + echo "${statefile%/.lgsm-workshop}" + return + fi + done +} + +# Reads a value from an installed mod's state file. Usage: fn_workshop_state +fn_workshop_state() { + local moddir + moddir="$(fn_workshop_moddir "${1}")" + if [ -n "${moddir}" ]; then + sed -n "s/^${2}=//p" "${moddir}/.lgsm-workshop" + fi +} + +# Works out which mods need downloading and which installed mods are no longer used. +fn_workshop_compare() { + workshopupdates=() + workshopremovals=() + local item + for item in "${workshopitems[@]}"; do + if [ "$(fn_workshop_state "${item}" timeupdated)" != "${workshoptimeupdated[${item}]}" ]; then + workshopupdates+=("${item}") + fi + done + if [ -d "${workshopdir}" ]; then + # Mods used by any instance sharing these serverfiles are kept. + local inuse=" ${workshopitems[*]} " + local listfile + for listfile in "${datadir}"/*-workshop.txt; do + if [ -f "${listfile}" ] && [ "${listfile}" != "${workshopmodlist}" ]; then + inuse+="$(grep -v '^#' "${listfile}" | tr '\n' ' ') " + fi + done + local statefile moddir + for statefile in "${workshopdir}"/*/.lgsm-workshop; do + if [ -f "${statefile}" ]; then + item="$(sed -n 's/^id=//p' "${statefile}")" + if [ -z "${item}" ]; then + moddir="${statefile%/*}" + moddir="${moddir##*/}" + item="${moddir#"${workshopprefix}"}" + fi + if [[ "${inuse}" != *" ${item} "* ]]; then + workshopremovals+=("${item}") + fi + fi + done + fi +} + +# Downloads Workshop items with a single SteamCMD login. Failed items are retried. +fn_workshop_download() { + local pending=("$@") + local attempt=0 + local item params + steamcmdlog="${lgsmlogdir}/${selfname}-steamcmd.log" + if [ -n "${workshopinplace}" ]; then + workshopdlroot="${serverfiles}" + else + workshopdlroot="${workshopdldir}" + rm -rf "${workshopdldir:?}" + mkdir -p "${workshopdldir}" + fi + if [ -d "${steamcmddir}" ]; then + cd "${steamcmddir}" || exit + fi + unbuffercommand=() + if [ "$(command -v unbuffer 2> /dev/null)" ]; then + unbuffercommand=("unbuffer") + fi + while [ "${#pending[@]}" -gt 0 ] && [ "${attempt}" -lt "${workshopretries}" ]; do + attempt=$((attempt + 1)) + params=(+force_install_dir "${workshopdlroot}" +login "${steamuser}" "${steampass}") + for item in "${pending[@]}"; do + params+=(+workshop_download_item "${workshopappid[${item}]}" "${item}") + done + params+=(+quit) + rm -f "${steamcmdlog:?}" + "${unbuffercommand[@]}" "${steamcmdcommand}" "${params[@]}" | uniq | tee -a "${lgsmlog}" "${steamcmdlog}" + + if grep -q "FAILED (" "${steamcmdlog}" || grep -q "Two-factor code mismatch" "${steamcmdlog}"; then + fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: Steam login failed" + fn_print_nl "Check steamuser and steampass in ${configdirserver}" + fn_script_log_fail "${commandaction} ${selfname}: ${remotelocation}: Steam login failed" + core_exit.sh + fi + + local failed=() + for item in "${pending[@]}"; do + if [ -z "$(find "${workshopdlroot}/steamapps/workshop/content/${workshopappid[${item}]}/${item}" -mindepth 1 -print -quit 2> /dev/null)" ]; then + failed+=("${item}") + fi + done + pending=("${failed[@]}") + if [ "${#pending[@]}" -gt 0 ] && [ "${attempt}" -lt "${workshopretries}" ]; then + fn_print_error2_nl "${commandaction} ${selfname}: ${remotelocation}: ${#pending[@]} item(s) did not download, retrying" + fn_script_log_error "${commandaction} ${selfname}: ${remotelocation}: ${#pending[@]} item(s) did not download, retrying" + fi + done + workshopfailed=("${pending[@]}") + if [ "${#workshopfailed[@]}" -gt 0 ]; then + fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: ${#workshopfailed[@]} item(s) failed to download" + for item in "${workshopfailed[@]}"; do + fn_print_nl "* ${workshoptitle[${item}]} (${item})" + fn_script_log_fail "${commandaction} ${selfname}: ${remotelocation}: ${workshoptitle[${item}]} (${item}) failed to download" + done + fn_print_nl "The Steam account must own the game for its Workshop items to download" + fi +} + +# Renames files and directories in a mod to lowercase, deepest first. +fn_workshop_lowercase() { + local path name lower + while IFS= read -r -d '' path; do + name="${path##*/}" + lower="${name,,}" + if [ -e "${path%/*}/${lower}" ]; then + fn_script_log_warn "Lowercase name already exists, not renaming: ${path}" + else + mv "${path}" "${path%/*}/${lower}" + fi + done < <(find "$1" -mindepth 1 -depth -name '*[[:upper:]]*' -print0) +} + +# Removes the BattlEye keys a mod installed, unless another installed mod also uses them. +fn_workshop_remove_keys() { + local item="$1" + local key statefile moddir + moddir="$(fn_workshop_moddir "${item}")" + for key in $(fn_workshop_state "${item}" keys); do + local shared="" + for statefile in "${workshopdir}"/*/.lgsm-workshop; do + if [ "${statefile}" != "${moddir}/.lgsm-workshop" ] && [[ " $(sed -n 's/^keys=//p' "${statefile}" 2> /dev/null) " == *" ${key} "* ]]; then + shared=1 + fi + done + if [ -z "${shared}" ]; then + rm -f "${serverfiles:?}/keys/${key}" + fi + done +} + +# Removes the links a mod added to the game's mod directory. +fn_workshop_remove_links() { + local link + while IFS= read -r link; do + if [ -n "${link}" ]; then + rm -f "${workshoplinkdir:?}/${link}" + fi + done < <(fn_workshop_state "$1" link) +} + +# Moves a downloaded item into the game's mod directory and prepares it for the game. +fn_workshop_install() { + local item="$1" + local src="${workshopdlroot}/steamapps/workshop/content/${workshopappid[${item}]}/${item}" + local dst="${workshopdir}/${workshopprefix}${item}" + local installed + local keys=() + local links=() + local key pak file rel + fn_print_dots "Installing ${workshoptitle[${item}]} (${item})" + installed="$(fn_workshop_moddir "${item}")" + if [ -n "${installed}" ]; then + fn_workshop_remove_keys "${item}" + fn_workshop_remove_links "${item}" + if [ "${installed}" != "${src}" ]; then + rm -rf "${installed:?}" + fi + fi + # A mod that is a single plugin folder is installed as that folder, for games that load mods by folder name. + if [ -n "${workshopflatten}" ]; then + local subdirs=() + mapfile -t subdirs < <(find "${src}" -mindepth 1 -maxdepth 1 -type d) + if [ "${#subdirs[@]}" -eq 1 ] && [ -z "$(find "${src}" -mindepth 1 -maxdepth 1 -type f -print -quit)" ]; then + dst="${workshopdir}/${subdirs[0]##*/}" + src="${subdirs[0]}" + fi + fi + if [ "${src}" != "${dst}" ]; then + if [ -e "${dst}" ]; then + fn_print_fail_nl "Installing ${workshoptitle[${item}]} (${item}): ${dst} already exists" + fn_script_log_fail "Installing ${workshoptitle[${item}]} (${item}): ${dst} already exists" + return + fi + mkdir -p "${workshopdir}" + if ! mv "${src}" "${dst}"; then + fn_print_fail_nl "Installing ${workshoptitle[${item}]} (${item})" + fn_script_log_fail "Installing ${workshoptitle[${item}]} (${item})" + core_exit.sh + fi + fi + if [ "${shortname}" == "arma3" ] || [ "${shortname}" == "dayz" ]; then + fn_workshop_lowercase "${dst}" + mkdir -p "${serverfiles}/keys" + while IFS= read -r -d '' key; do + cp -f "${key}" "${serverfiles}/keys/" + keys+=("${key##*/}") + done < <(find "${dst}" -type f -name '*.bikey' -print0) + elif [ "${shortname}" == "sb" ]; then + mkdir -p "${workshoplinkdir}" + while IFS= read -r -d '' pak; do + ln -srfn "${pak}" "${workshoplinkdir}/workshop-${item}-${pak##*/}" + links+=("workshop-${item}-${pak##*/}") + done < <(find "${dst}" -maxdepth 1 -type f -name '*.pak' -print0) + elif [ "${shortname}" == "l4d2" ]; then + # Legacy Workshop items download as _legacy.bin, which is the addon's .vpk. + pak="$(find "${dst}" -maxdepth 1 -type f \( -name '*.vpk' -o -name '*_legacy.bin' \) -print -quit)" + if [ -n "${pak}" ]; then + mkdir -p "${workshoplinkdir}" + ln -srfn "${pak}" "${workshoplinkdir}/${item}.vpk" + links+=("${item}.vpk") + fi + elif [ "${shortname}" == "sol" ]; then + # Soldat items mirror the server's maps, textures and scenery-gfx directories. The server only finds lowercase .pms maps. + while IFS= read -r -d '' file; do + rel="${file#"${dst}/"}" + if [[ "${rel,,}" == maps/*.pms ]]; then + rel="${rel%.*}.pms" + fi + if [ -e "${workshoplinkdir}/${rel}" ] || [ -L "${workshoplinkdir}/${rel}" ]; then + fn_script_log_warn "Not linking ${rel} from ${workshoptitle[${item}]} (${item}): file already exists" + continue + fi + mkdir -p "${workshoplinkdir}/${rel%/*}" + ln -sr "${file}" "${workshoplinkdir}/${rel}" + links+=("${rel}") + done < <(find "${dst}" -mindepth 2 -type f -print0) + fi + local modname="" + if [ "${shortname}" == "col" ] && [ -f "${dst}/modInfo.json" ]; then + modname="$(jq -r 'if type == "array" then .[0].name else .name end // empty' "${dst}/modInfo.json" 2> /dev/null)" + fi + { + echo "id=${item}" + echo "modname=${modname}" + echo "title=${workshoptitle[${item}]}" + echo "timeupdated=${workshoptimeupdated[${item}]}" + echo "keys=${keys[*]}" + if [ "${#links[@]}" -gt 0 ]; then + printf 'link=%s\n' "${links[@]}" + fi + } > "${dst}/.lgsm-workshop" + fn_print_ok_nl "Installing ${workshoptitle[${item}]} (${item})" + fn_script_log_pass "Installing ${workshoptitle[${item}]} (${item})" +} + +# Removes an installed mod that is no longer in workshopmods. +fn_workshop_remove() { + local item="$1" + local title moddir + title="$(fn_workshop_state "${item}" title)" + moddir="$(fn_workshop_moddir "${item}")" + workshopremovednames+=("$(fn_workshop_state "${item}" modname)") + fn_print_dots "Removing ${title} (${item})" + fn_workshop_remove_keys "${item}" + fn_workshop_remove_links "${item}" + if [ -n "${moddir}" ]; then + rm -rf "${moddir:?}" + fi + fn_print_ok_nl "Removing ${title} (${item})" + fn_script_log_pass "Removing ${title} (${item})" +} + +# Barotrauma only loads mods listed in config_player.xml. Replaces LinuxGSM's entries with the installed mods, in order. +fn_workshop_bt_packages() { + local config="${serverfiles}/config_player.xml" + local item entries="" + if [ ! -f "${config}" ]; then + fn_print_warn_nl "${config} not found. Start the server once, then run ./${selfname} workshop-update to enable Workshop mods" + fn_script_log_warn "${config} not found, Workshop mods not enabled" + return + fi + sed -z -i 's##\n #' "${config}" + for item in "${workshopremovals[@]}" "${workshopitems[@]}"; do + sed -z -i -E "s#[[:space:]]*##g" "${config}" + done + for item in "${workshopitems[@]}"; do + if [ -f "${workshopdir}/${item}/filelist.xml" ]; then + entries+="\\n " + fi + done + sed -z -i -E "s#([[:space:]]*)#${entries}\\1#" "${config}" + sed -z -i -E 's#[[:space:]]*##' "${config}" +} + +# Colony Survival only loads mods enabled in each world's worldconfig.json. Replaces LinuxGSM's entries with the installed mods, in order. +fn_workshop_col_worlds() { + local item name worldconfig managedjson enabledjson + local managed=("${workshopremovednames[@]}") + local enabled=() + for item in "${workshopitems[@]}"; do + name="$(fn_workshop_state "${item}" modname)" + if [ -n "${name}" ]; then + managed+=("${name}") + enabled+=("${name}") + fi + done + managedjson="$(jq -cn '$ARGS.positional' --args "${managed[@]}")" + enabledjson="$(jq -cn '$ARGS.positional' --args "${enabled[@]}")" + for worldconfig in "${serverfiles}"/gamedata/savegames/*/worldconfig.json; do + if [ ! -f "${worldconfig}" ]; then + fn_print_warn_nl "No Colony Survival world found. Start the server once, then run ./${selfname} workshop-update to enable Workshop mods" + fn_script_log_warn "No Colony Survival world found, Workshop mods not enabled" + return + fi + if jq -c --argjson managed "${managedjson}" --argjson enabled "${enabledjson}" ' + (.ModConfigEntries // []) as $old + | ($old | map({key: .ModName, value: .}) | from_entries) as $existing + | .ModConfigEntries = [$old[] | select(.ModName as $n | any($managed[]; . == $n) | not)] + + [$enabled[] | . as $n | ($existing[$n] // {ModName: $n, ModVersionLastKnown: "---"}) | .Enabled = true] + ' "${worldconfig}" > "${worldconfig}.tmp" 2> /dev/null; then + mv "${worldconfig}.tmp" "${worldconfig}" + else + rm -f "${worldconfig}.tmp" + fn_print_warn_nl "Unable to update ${worldconfig}" + fn_script_log_warn "Unable to update ${worldconfig}" + fi + done +} + +# Installs downloaded items and removes unused ones. Downloads happen first, so the server only stops for this step. +fn_workshop_apply() { + local item + workshopremovednames=() + for item in "${workshopinstalls[@]}"; do + fn_workshop_install "${item}" + done + for item in "${workshopremovals[@]}"; do + fn_workshop_remove "${item}" + done + if [ "${shortname}" == "bt" ]; then + fn_workshop_bt_packages + elif [ "${shortname}" == "col" ]; then + fn_workshop_col_worlds + fi + rm -rf "${workshopdldir:?}" +} + +# Saves the resolved mod order so start can build the mod list without querying Steam. +fn_workshop_save_list() { + if [ "${#workshopitems[@]}" -eq 0 ]; then + rm -f "${workshopmodlist}" + return + fi + { + echo "# workshopmods=${workshopmods}" + printf '%s\n' "${workshopitems[@]}" + } > "${workshopmodlist}" +} + +# Checks for Workshop mod updates and, for update commands, applies them. +fn_workshop_update() { + remotelocation="Steam Workshop" + fn_print_dots "Checking for update: ${remotelocation}" + fn_workshop_resolve + if [ "${#workshopitems[@]}" -gt 0 ]; then + fn_workshop_get_details + fi + fn_workshop_compare + fn_print_ok_nl "Checking for update: ${remotelocation}" + fn_script_log_info "Checking for update: ${remotelocation}" + + local item + if [ "${#workshopupdates[@]}" -eq 0 ] && [ "${#workshopremovals[@]}" -eq 0 ]; then + fn_print "\n" + fn_print_nl "${bold}${underline}No update${default} available" + fn_print_nl "* Workshop mods: ${#workshopitems[@]}" + fn_print "\n" + fn_script_log_info "No update available: ${remotelocation}" + if [ "${commandname}" != "CHECK-UPDATE" ]; then + fn_workshop_save_list + fi + return + fi + + fn_print "\n" + fn_print_nl "${bold}${underline}Update${default} available" + for item in "${workshopupdates[@]}"; do + if [ -n "$(fn_workshop_moddir "${item}")" ]; then + fn_print_nl "* Update: ${workshoptitle[${item}]} (${item})" + else + fn_print_nl "* Install: ${workshoptitle[${item}]} (${item})" + fi + fn_script_log_info "Update available: ${workshoptitle[${item}]} (${item})" + done + for item in "${workshopremovals[@]}"; do + fn_print_nl "* Remove: $(fn_workshop_state "${item}" title) (${item})" + fn_script_log_info "Remove: $(fn_workshop_state "${item}" title) (${item})" + done + fn_print "\n" + + if [ "${commandname}" == "CHECK-UPDATE" ]; then + return + fi + + fn_workshop_save_list + date '+%s' > "${lockdir:?}/update.lock" + workshopinstalls=() + workshopfailed=() + if [ "${#workshopupdates[@]}" -gt 0 ]; then + fn_print_start_nl "${remotelocation}" + fn_workshop_download "${workshopupdates[@]}" + for item in "${workshopupdates[@]}"; do + if [[ " ${workshopfailed[*]} " != *" ${item} "* ]]; then + workshopinstalls+=("${item}") + fi + done + fi + if [ "${#workshopinstalls[@]}" -eq 0 ] && [ "${#workshopremovals[@]}" -eq 0 ]; then + rm -rf "${workshopdldir:?}" + return + fi + + check_status.sh + if [ "${status}" == "0" ]; then + fn_workshop_apply + else + fn_print_restart_warning + exitbypass=1 + command_stop.sh + fn_firstcommand_reset + fn_workshop_apply + exitbypass=1 + command_start.sh + fn_firstcommand_reset + fi + unset exitbypass +} + +# Adds installed Workshop mods to the start parameters, in workshopmods order: -mod= for Arma 3 and DayZ, loadmod for Hurtworld. +fn_workshop_mods_startparameters() { + if [ -n "${workshopmodsadded}" ]; then + return + fi + workshopmodsadded=1 + local items=() + if [ -f "${workshopmodlist}" ]; then + mapfile -t items < <(grep -v '^#' "${workshopmodlist}") + if [ "$(sed -n 's/^# workshopmods=//p' "${workshopmodlist}")" != "${workshopmods}" ]; then + fn_print_warn_nl "workshopmods has changed. Run ./${selfname} workshop-update to apply it" + fn_script_log_warn "workshopmods has changed. Run ./${selfname} workshop-update to apply it" + fi + else + fn_workshop_config_ids + items=("${workshopconfigids[@]}") + fi + local workshopmodsparam="" + local missing=0 + local item + for item in "${items[@]}"; do + if [ -d "${workshopdir}/${workshopprefix}${item}" ] && [ "${shortname}" == "hw" ]; then + workshoploadmods+=";loadmod ${item}" + elif [ -d "${workshopdir}/${workshopprefix}${item}" ]; then + workshopmodsparam+="${workshopmodsparam:+\\;}workshop/${workshopprefix}${item}" + else + missing=$((missing + 1)) + fi + done + if [ "${missing}" -gt 0 ]; then + fn_print_warn_nl "${missing} Workshop mod(s) not installed. Run ./${selfname} workshop-update to install them" + fn_script_log_warn "${missing} Workshop mod(s) not installed" + fi + if [ -n "${workshopmodsparam}" ]; then + mods="${mods:+${mods}\\;}${workshopmodsparam}" + fi +} diff --git a/linuxgsm.sh b/linuxgsm.sh index 9274a071b6..cbf7f50a9c 100755 --- a/linuxgsm.sh +++ b/linuxgsm.sh @@ -24,7 +24,7 @@ if [ -f ".dev-debug" ]; then set -x fi -version="v26.2.0" +version="v26.5.0" shortname="core" gameservername="core" commandname="CORE" @@ -70,17 +70,32 @@ core_modules.sh() { } # Bootstrap +# Exits during bootstrap. core_exit.sh is only usable once core_modules.sh (which defines it) +# and core_dl.sh (fn_fetch_module, which it uses) are loaded, so fall back to a plain exit. +fn_bootstrap_exit() { + if type core_exit.sh > /dev/null 2>&1 && type fn_fetch_module > /dev/null 2>&1; then + core_exit.sh + else + exit "${1:-1}" + fi +} + # Fetches the core modules required before passed off to core_dl.sh. fn_bootstrap_fetch_trap() { echo -e "" - echo -en "downloading ${local_filename}" - fn_print_canceled_eol_nl - fn_script_log_info "Downloading ${local_filename}...CANCELED" rm -f "${local_filedir:?}/${local_filename}" - echo -en "downloading ${local_filename}" - fn_print_removed_eol_nl - fn_script_log_info "Downloading ${local_filename}...REMOVED" - core_exit.sh + # Message and logging functions come from core_messages.sh, which may not be loaded yet. + if type fn_print_canceled_eol_nl > /dev/null 2>&1; then + echo -en "downloading ${local_filename}" + fn_print_canceled_eol_nl + echo -en "downloading ${local_filename}" + fn_print_removed_eol_nl + fn_script_log_info "Downloading ${local_filename}...CANCELED" + fn_script_log_info "Downloading ${local_filename}...REMOVED" + else + echo -e "downloading ${local_filename} ... CANCELED (removed)" + fi + fn_bootstrap_exit 130 } # Fetches modules from the Git repo during first download. @@ -146,7 +161,7 @@ fn_bootstrap_fetch_file() { fi # Trap will remove part downloaded files if canceled. trap fn_bootstrap_fetch_trap INT - curlcmd=(curl --connect-timeout 3 --fail -L -o "${local_filedir}/${local_filename}" --retry 2 -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.${randomint}.212 Safari/537.36") + curlcmd=(curl --connect-timeout 10 --fail -L -o "${local_filedir}/${local_filename}" --retry 2 -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.${randomint}.212 Safari/537.36") # if is large file show progress, else be silent local exitcode="" @@ -175,14 +190,15 @@ fn_bootstrap_fetch_file() { if [ "${exitcode}" -ne 0 ]; then if [ ${counter} -ge 2 ]; then echo -e " ... FAIL" - if [ -f "${lgsmlog}" ]; then + # Logging functions come from core_messages.sh, which may not be loaded yet during bootstrap. + if [ -f "${lgsmlog}" ] && type fn_script_log_fail > /dev/null 2>&1; then fn_script_log_fail "Downloading ${local_filename}..." fn_script_log_fail "${fileurl}" fi - core_exit.sh + fn_bootstrap_exit 1 else echo -e " ... ERROR" - if [ -f "${lgsmlog}" ]; then + if [ -f "${lgsmlog}" ] && type fn_script_log_error > /dev/null 2>&1; then fn_script_log_error "Downloading ${local_filename}..." fn_script_log_error "${fileurl}" fi @@ -191,7 +207,7 @@ fn_bootstrap_fetch_file() { echo -en " ... OK" sleep "0.1" echo -e "\033\\r" - if [ -f "${lgsmlog}" ]; then + if [ -f "${lgsmlog}" ] && type fn_script_log_pass > /dev/null 2>&1; then fn_script_log_pass "Downloading ${local_filename}..." fi @@ -243,13 +259,17 @@ fn_bootstrap_fetch_file_github() { # Installer menu. fn_print_center() { - columns=$(tput cols) + # Fall back to 80 columns when there is no terminal. + columns="${COLUMNS:-$(tput cols 2> /dev/null)}" + columns="${columns:-80}" line="$*" printf "%*s\n" $(((${#line} + columns) / 2)) "${line}" } fn_print_horizontal() { - printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' "=" + # Fall back to 80 columns when there is no terminal; bash 5.3+ rejects an empty printf width. + local columns="${COLUMNS:-$(tput cols 2> /dev/null)}" + printf '%*s\n' "${columns:-80}" '' | tr ' ' "=" } # Bash menu. @@ -533,6 +553,9 @@ else elif grep -qE "^[[:blank:]]*startparameters=" "${configdirserver}/_default.cfg"; then eval startparameters="$(sed -nr 's/^ *startparameters=(.*)$/\1/p' "${configdirserver}/_default.cfg")" fi + if [ -n "${extraparams}" ]; then + startparameters="${startparameters} ${extraparams}" + fi # reload preexecutable. if grep -qE "^[[:blank:]]*preexecutable=" "${configdirserver}/secrets-${selfname}.cfg"; then diff --git a/package-lock.json b/package-lock.json index 581f6ea8a8..cac32dc8c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -358,9 +358,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.3.0.tgz", + "integrity": "sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==" }, "node_modules/http2-wrapper": { "version": "2.2.1",