From 3951cea25b363231d9602cf4c9390f78f104cbb2 Mon Sep 17 00:00:00 2001 From: James Ives Date: Sat, 13 Jul 2024 15:49:03 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Improve=20overall=20docu?= =?UTF-8?q?mentation=20structure=20(#22)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build: add auto-labeler and sponsors information (#17) * Update README.md * Create sponsors.yml * Create label.yml * test: resolve issue thing * style: remove typo * chore: update * build(deps): bump softprops/action-gh-release from 1 to 2 (#18) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump actions/checkout from 3 to 4 (#19) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs: 📝 Improve documentation (#21) * docs: docker whale image * Update README.md * Update README.md * Update README.md * docs: add more examples * docs: add more examples * docs: improve docs * Update README.md * Update README.md * Update README.md * test * Update BUILDING_AN_IMAGE.md * Update label.yml * Delete crowbar.png * Update README.md * Update sponsors.yml * docs: more doc improvements/spell checks etc * Deploying to beta from @ JamesIves/hlds-docker@ee94d7ce3c59b132a08827d977fb9df8e620a0b7 🚀 * Update sponsors.yml * Update README.md * docs: server -> joinable not error * Update CUSTOM_MODS.md * Update SERVER_CONFIGS_AND_PLUGINS.md --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JamesIves --- .github/docs/crowbar.png | Bin 44184 -> 0 bytes .github/docs/docker.svg | 12 +++ .github/workflows/label.yml | 95 ++++++++++++++++++++ .github/workflows/publish.yml | 2 +- .github/workflows/sponsors.yml | 29 ++++++ CONTRIBUTING.md | 8 +- README.md | 140 ++++++----------------------- docker-compose.local.yml | 16 ++++ docker-compose.yml | 12 +-- docs/BUILDING_AN_IMAGE.md | 50 +++++++++++ docs/CUSTOM_MODS.md | 19 ++++ docs/SERVER_CONFIGS_AND_PLUGINS.md | 17 ++++ 12 files changed, 277 insertions(+), 123 deletions(-) delete mode 100644 .github/docs/crowbar.png create mode 100644 .github/docs/docker.svg create mode 100644 .github/workflows/label.yml create mode 100644 .github/workflows/sponsors.yml create mode 100644 docker-compose.local.yml create mode 100644 docs/BUILDING_AN_IMAGE.md create mode 100644 docs/CUSTOM_MODS.md create mode 100644 docs/SERVER_CONFIGS_AND_PLUGINS.md diff --git a/.github/docs/crowbar.png b/.github/docs/crowbar.png deleted file mode 100644 index 0f54c395ed2ead5d3d10ce8ebd007d180bd304c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44184 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 Z-28AL(Roh8hrpL0b!8o;8U>rs{{orH4Uzx= diff --git a/.github/docs/docker.svg b/.github/docs/docker.svg new file mode 100644 index 0000000..1f07539 --- /dev/null +++ b/.github/docs/docker.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml new file mode 100644 index 0000000..94f430e --- /dev/null +++ b/.github/workflows/label.yml @@ -0,0 +1,95 @@ +name: Label Pull Requests 🏷️ + +on: + pull_request: + types: [opened, reopened, labeled, unlabeled, synchronize] + +permissions: + pull-requests: write + contents: read + +jobs: + assign-labels: + runs-on: ubuntu-latest + name: Assign labels in pull request 🏷️ + if: github.event.pull_request.merged == false + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v4 + + - name: Assign Labels 🏷️ + id: action-assign-labels + uses: mauroalderete/action-assign-labels@v1 + with: + pull-request-number: ${{ github.event.pull_request.number }} + github-token: ${{ secrets.GITHUB_TOKEN }} + conventional-commits: | + conventional-commits: + - type: 'fix' + nouns: ['FIX', 'Fix', 'fix', 'FIXED', 'Fixed', 'fixed'] + labels: ['bug 🐝', 'fix 🐝'] + - type: 'feature' + nouns: ['FEATURE', 'Feature', 'feature', 'FEAT', 'Feat', 'feat'] + labels: ['feature ✨'] + - type: 'breaking_change' + nouns: ['BREAKING CHANGE', 'BREAKING', 'MAJOR'] + labels: ['breaking 💥'] + - type: 'documentation' + nouns: ['doc', 'docu', 'docs', 'document', 'documentation'] + labels: ['documentation 📖'] + - type: 'build' + nouns: ['build', 'rebuild'] + labels: ['build 🔧'] + - type: 'chore' + nouns: ['chore', 'tidy', 'cleanup'] + labels: ['chore 🧹'] + - type: 'dependencies' + nouns: ['dependency', 'dependencies', 'package', 'packages', 'bump', 'dependabot'] + labels: ['dependencies 🤖'] + - type: 'duplicate' + nouns: ['duplicate', 'dupe', 'copy'] + labels: ['duplicate 2️⃣'] + - type: 'good_first_issue' + nouns: ['good first issue', 'beginner', 'newcomer', 'first-timer'] + labels: ['good first issue 🍩'] + - type: 'help_wanted' + nouns: ['help wanted', 'need help', 'assistance required'] + labels: ['help wanted ❕'] + - type: 'proposal' + nouns: ['proposal', 'suggest', 'suggestion'] + labels: ['proposal 🔮'] + - type: 'question' + nouns: ['question', 'inquiry', 'query'] + labels: ['question ❓'] + - type: 'test' + nouns: ['test', 'testing', 'tests'] + labels: ['test 🧪'] + - type: 'triage' + nouns: ['triage', 'sort', 'prioritize'] + labels: ['triage ⚠️'] + - type: 'wontfix' + nouns: ['wontfix', 'will not fix', 'not fixing'] + labels: ['wontfix 🔨'] + - type: 'style' + nouns: ['style', 'formatting', 'format'] + labels: ['style 🎀'] + - type: 'security' + nouns: ['security', 'secure', 'safety'] + labels: ['security 🔒'] + - type: 'performance' + nouns: ['performance', 'speed', 'optimization'] + labels: ['performance 🚀'] + - type: 'refactor' + nouns: ['refactor', 'refactoring', 'rework'] + labels: ['refactor 🛠'] + - type: 'release' + nouns: ['release', 'deploy', 'deployment'] + labels: ['release 🚀'] + - type: 'ci' + nouns: ['ci', 'continuous integration', 'CI/CD'] + labels: ['ci 🚀'] + - type: 'hacktoberfest' + nouns: ['hacktoberfest', 'october', 'open source'] + labels: ['hacktoberfest 🎃'] + maintain-labels-not-matched: false + apply-changes: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1922ae4..8416064 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -111,7 +111,7 @@ jobs: - name: Create Release 🚀 id: create_release if: github.ref == 'refs/heads/main' - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.create_tag.outputs.new_tag }} name: ${{ steps.create_tag.outputs.new_tag }} diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml new file mode 100644 index 0000000..46f93b3 --- /dev/null +++ b/.github/workflows/sponsors.yml @@ -0,0 +1,29 @@ +name: Publish Sponsors 💖 + +on: + workflow_dispatch: + schedule: + - cron: 30 15 * * 0-6 +permissions: + contents: write +jobs: + generate-sponsors: + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v4 + + - name: Generate Sponsors 💖 + uses: JamesIves/github-sponsors-readme-action@v1 + with: + token: ${{ secrets.PAT }} + file: "README.md" + template: '{{{ login }}}  ' + active-only: false + + - name: Deploy to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + branch: beta + folder: "." + commit-message: "chore: Update sponsors 💖 [skip ci]" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d9e8d9a..2131dcf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,8 @@ -# Contributing ✨ +# Contributing I appreciate your interest in contributing to this project. Please review the general process and scope before starting a contribution. -## Scope 🔍 +## Scope The four main requirements for this project are: @@ -11,12 +11,12 @@ The four main requirements for this project are: 3. Have the ability to run servers for custom mods. 4. Only support legal usage of Steam and Valve's titles. **It will not, and never will, support the ability to circumvent any licensing or other restrictions Valve imposes.** The project maintainers will report any shady behaviour to Valve and GitHub. -## Process ✈️ +## Process 1. File an issue on the [Issues board](https://github.com/JamesIves/hlds-docker/issues), or create a discussion on the [Discussions board](https://github.com/JamesIves/hlds-docker/discussions). 2. Once discussed and agreed upon, clone the project. 3. Make your changes. -4. Validate your changes; at the very least, please build the image and start a server. +4. Validate your changes; at the very least, please build the image and start a server. [You can learn how to build the images using the guide located here](docs/BUILDING_AN_IMAGE.md). 5. Submit a pull request to the `beta` branch. 6. Once reviewed, your changes will be made available on DockerHub via the `-beta` tag, for example `jives/hlds:cstrike-beta`. 7. After some more tests, changes will be made sent to the `main` branch where the production images will be published. diff --git a/README.md b/README.md index 6175026..4895dbc 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,37 @@ -# Half-Life Dedicated Server With Docker 🐋 📦 +Docker in the Half-Life Colours -Crowbar +# hlds-docker -Creates a [Half-Life Dedicated Server](https://help.steampowered.com/en/faqs/view/081A-106F-B906-1A7A) instance using [Docker](https://www.docker.com). You can run any games the Half-Life Dedicated Server client supports out of the box, including the ability to add custom configurations, mods and plugins. +[Half-Life Dedicated Server](https://help.steampowered.com/en/faqs/view/081A-106F-B906-1A7A) powered by [Docker](https://www.docker.com). It supports all the classic [GoldSrc](https://developer.valvesoftware.com/wiki/GoldSrc) Half-Life games and mods, including the ability to add custom configurations and plugins. Special thank you to all the past and present [GitHub Sponsors](https://github.com/sponsors/JamesIves) 💖. Chooksta69  MattWillFlood  jonathan-milan-pollock  raoulvdberge  robjtede  hadley  kevinchalet  Yousazoe  github  annegentle  planetoftheweb  melton1968  szepeviktor  sckott  provinzkraut  electrovir  Griefed  MontezumaIves   -## Setup ⚙️ +## Getting Started 🚀 Before starting, ensure you have the [Docker daemon](https://www.docker.com/) and the [Docker CLI tool](https://docs.docker.com/engine/reference/commandline/cli/) installed and available. > [!IMPORTANT] > The following steps will not work if you use an ARM architecture system. For best results, use a system running x86-64. -### Pre-Built Images +You can run the following in your terminal to get started as quickly as possible. Adjust the image name (`jives/hlds`) so the tag corresponds with the game you want to use. Additionally, you can adjust the server startup arguments by modifying the `command` property; [for a list of available arguments, visit the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server). -If you're just looking to start a server as quickly as possible you can follow these steps to use a pre-built image on [Docker Hub](https://hub.docker.com/repository/docker/jives/hlds) or the [GitHub Container Registry](https://github.com/JamesIves/hlds-docker/pkgs/container/hlds). - -1. Create a `docker-compose.yml` file by copying and pasting the example below. Adjust the `image` property so the tag name corresponds with the game you want to use. Additionally you can adjust the server startup arguments by modifying the `command` property; [for a list of available arguments, visit the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server). - -> [!NOTE] -> In the majority of cases you'll need to specify `+map` for the server to be joinable. - -```yml -services: - hlds: - build: docker - # 📣 Adjust the image value here with the desired game you want the server to use. - image: jives/hlds:cstrike - volumes: - - "./config:/temp/config" - - "./mods:/temp/mods" - ports: - - "27015:27015/udp" - - "27015:27015" - - "26900:2690/udp" - environment: - - GAME=${GAME} - # 📣 Modify your server startup commands here. - # 📣 Remember: Stating map is based on the game, and will likely be different between images. - command: +maxplayers 12 +map cs_italy +```bash +docker run -d \ + --name hlds \ + -v "$(pwd)/config:/temp/config" \ + -v "$(pwd)/mods:/temp/mods" \ + -p 27015:27015/udp \ + -p 27015:27015 \ + -p 26900:26900/udp \ + -e GAME=${GAME} \ + jives/hlds:cstrike \ + "+maxplayers 12 +map cs_italy" # 📣 Modify your server startup commands here. You can specify the image with the desired game you want the server to run in the line above. ``` > [!TIP] -> Available images include: +> The available images are below. When changing the game, be sure to adjust the `+map` parameter, as it may cause the server not to be joinable if the map is unavailable. > > - `jives/hlds:valve` ([Half-Life Deathmatch](https://store.steampowered.com/app/70/HalfLife/)) > - `jives/hlds:cstrike` ([Counter-Strike](https://store.steampowered.com/app/10/CounterStrike/)) @@ -55,94 +41,22 @@ services: > - `jives/hlds:ricohet` ([Ricochet](https://store.steampowered.com/app/60/Ricochet/)) > - `jives/hlds:dod` ([Day of Defeat](https://store.steampowered.com/app/30/Day_of_Defeat/)) > - `jives/hlds:tfc` ([Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)) - -2. Start the image. Once the Half-Life Dedicated Server client starts, you'll receive a stream of messages, including the server's public IP address and any startup errors. - -```bash -docker compose up -``` - -3. Connect to your server via the IP address by loading the game on [Steam](https://store.steampowered.com/) and start playing. You must own a copy of the game on Steam in order to play. ⌨️ - -### Building an Image - -If you want to build an image yourself, you can follow the steps below. This can be useful in cases where you want to make changes to the build scripts. - -1. Clone this project. -2. Define the game you want the server to run. You can do this by setting an environment variable on your command line. - -```bash -export GAME=cstrike -``` - -Before continuing to the next steps, verify that the environment variable is set by running `echo $GAME` in your terminal. It should send back the variable you just set. - -> [!TIP] -> Available options include: > -> - `valve` ([Half-Life Deathmatch](https://store.steampowered.com/app/70/HalfLife/)) -> - `cstrike` ([Counter-Strike](https://store.steampowered.com/app/10/CounterStrike/)) -> - `czero` ([Counter-Strike Condition Zero](https://store.steampowered.com/app/80/CounterStrike_Condition_Zero/)) -> - `dmc` ([Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/)) -> - `gearbox` ([Half-Life Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)) -> - `ricohet` ([Ricochet](https://store.steampowered.com/app/60/Ricochet/)) -> - `dod` ([Day of Defeat](https://store.steampowered.com/app/30/Day_of_Defeat/)) -> - `tfc` ([Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)) - -3. Build the image. - -```sh -docker compose build -``` +> Container images are alternatively available on the [GitHub Container Registry](https://github.com/JamesIves/hlds-docker/pkgs/container/hlds). -4. If you want to modify the server startup arguments, you can provide a `command` property within `docker-compose.yml`; [for a list of available arguments, visit the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server). +Once the command finishes, you can connect to your server via the public IP address by loading the game on [Steam](https://steampowered.com). **You must own a copy of the game on Steam to play**. > [!NOTE] -> In the majority of cases you'll need to specify `+map` for the server to be joinable. +> If you cannot join the server, you can check for errors in the server logs by running `docker ps` to get the container id followed by `docker logs `. -```yml -services: - hlds: - command: +maxplayers 16 +map cs_italy -``` +### Docker Compose -5. Start the image. Once the Half-Life Dedicated Server client starts, you'll receive a stream of messages, including the server's public IP address and any startup errors. +If you'd prefer to configure your server using [Docker Compose](https://docs.docker.com/compose/), you can pull down the project repository to your system and run `docker compose up` from the root. Make any modifications you need, such as changing the game image and server startup commands in [docker-compose.yml](docker-compose.yml) before running `docker compose up`. -```bash -docker compose up -``` - -6. Connect to your server via the IP address by loading the game on [Steam](https://store.steampowered.com/) and start playing. You must own a copy of the game on Steam in order to play. ⌨️ - -## Server Configuration 🔧 - -### Configs and Plugins - -If you wish to add server configurations, such as add-ons, plugins, map rotations, etc, you can add them to the `config` directory. Any configuration files will be copied into the container on start and placed within the folder for the specified game. For example, if you set the game as `cstrike`, the contents of the config folder will be placed within the `cstrike` directory on the server. - -### Custom Mods - -If you want to run a custom mod, you can do so with the `mods` directory. Similar to the `config` directory, this folder will be copied into your container on start alongside the other game folders. - -1. Add your mod files as a sub-directory of `mods`. For example if the mod name is `decay`, you'd place it in `mods/decay`. -2. Define the `GAME` environment variable so it points to your mod name. This works if you're using a pre-built image `docker-compose.yml` or by building one yourself. - -```bash -export GAME=decay -``` - -3. Build the image. If you don't want to build the image, I suggest using the pre-built `jives/hlds:valve` image. - -```bash -docker compose build -``` - -4. Start the image. Most Half-Life mods require _specific_ startup arguments, refer to the [Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server) and the instructions for the mod you're trying to run for more details. You can find details about how to add these above. - -```bash -docker compose up -``` +## Advanced Setup ⚙️ -## Ownership 🧰 +To customize the server client further, please check out the following advanced setup guides. -The Half-Life Dedicated Server client, Steam, SteamCMD and the titles themselves are property and ownership of [Valve Software](https://valvesoftware.com). All this software does is make it easier to interface with their provided tooling. +- [Server Configs and Plugins](docs/SERVER_CONFIGS_AND_PLUGINS.md) +- [Custom Mods](docs/CUSTOM_MODS.md) +- [Building a Custom Image](docs/BUILDING_AN_IMAGE.md) diff --git a/docker-compose.local.yml b/docker-compose.local.yml new file mode 100644 index 0000000..5b5ed16 --- /dev/null +++ b/docker-compose.local.yml @@ -0,0 +1,16 @@ +services: + hlds: + build: + context: . + args: + - GAME=${GAME} + volumes: + - "./config:/temp/config" + - "./mods:/temp/mods" + ports: + - "27015:27015/udp" + - "27015:27015" + - "26900:2690/udp" + environment: + - GAME=${GAME} + command: +maxplayers 12 +log on diff --git a/docker-compose.yml b/docker-compose.yml index 5b5ed16..04d3041 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,9 @@ services: hlds: - build: - context: . - args: - - GAME=${GAME} + build: docker + # 📣 Adjust the image value here with the desired game you want the server to use. + image: jives/hlds:cstrike + # 📣 Learn more about these volumes in the advanced setup guides. volumes: - "./config:/temp/config" - "./mods:/temp/mods" @@ -13,4 +13,6 @@ services: - "26900:2690/udp" environment: - GAME=${GAME} - command: +maxplayers 12 +log on + # 📣 Modify your server startup commands here. + # 📣 Remember: Stating map is based on the game, and will likely be different between images. + command: +maxplayers 12 +map cs_italy diff --git a/docs/BUILDING_AN_IMAGE.md b/docs/BUILDING_AN_IMAGE.md new file mode 100644 index 0000000..d75ea47 --- /dev/null +++ b/docs/BUILDING_AN_IMAGE.md @@ -0,0 +1,50 @@ +# Building an Image + +If you want to build an image yourself, follow the steps below. This can be useful in cases where you want to make changes to the build scripts or add custom functionality. It is also useful for testing changes before submitting a contribution to the project. + +1. Clone this project locally. +2. Define the game you want the server to run. You can do this by setting an environment variable on your command line. + +```bash +export GAME=cstrike +``` + +Before continuing to the following steps, verify that the environment variable is set by running `echo $GAME` in your terminal. It should send back the variable you just set. + +> [!TIP] +> Available options include the following, these names are recognized by the `app_set_config 90 mod` command in `hlds.txt`. +> +> - `valve` ([Half-Life Deathmatch](https://store.steampowered.com/app/70/HalfLife/)) +> - `cstrike` ([Counter-Strike](https://store.steampowered.com/app/10/CounterStrike/)) +> - `czero` ([Counter-Strike Condition Zero](https://store.steampowered.com/app/80/CounterStrike_Condition_Zero/)) +> - `dmc` ([Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/)) +> - `gearbox` ([Half-Life Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)) +> - `ricohet` ([Ricochet](https://store.steampowered.com/app/60/Ricochet/)) +> - `dod` ([Day of Defeat](https://store.steampowered.com/app/30/Day_of_Defeat/)) +> - `tfc` ([Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)) + +3. Build the image. + +```sh +docker compose -f docker-compose.local.yml build +``` + +4. If you want to modify the server startup arguments, you can provide a `command` property within `docker-compose.local.yml`; [for a list of available arguments, visit the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server). + +> [!NOTE] +> In most cases, you'll need to specify `+map` for the server to be joinable. + +```yml +services: + hlds: + command: +maxplayers 16 +map cs_italy +``` + +5. Start the image. Once the Half-Life Dedicated Server client starts, you'll receive a stream of messages, including the server's public IP address and any startup errors. + +```bash +docker compose -f docker-compose.local.yml up +``` + +6. Connect to your server via the public IP address by loading the game on [Steam](https://store.steampowered.com/). To play, you must own a copy of the game on Steam. +7. _Optional_: If you want to start a custom mod, you can modify your `$GAME` environment variable once the image is built before running `docker compose -f docker-compose.local.yml up`. This allows you to add custom scripts to the server image while telling the dedicated server client what mod to use. diff --git a/docs/CUSTOM_MODS.md b/docs/CUSTOM_MODS.md new file mode 100644 index 0000000..bcb8124 --- /dev/null +++ b/docs/CUSTOM_MODS.md @@ -0,0 +1,19 @@ +# Custom Mods + +If you want to run a custom mod, you can do so with the `mods` directory. + +> [!NOTE] +> The startup examples posted in the project README already have this directory volume mapped accordingly. If you've strayed from the suggested setup, [please refer back to it to get started](../README.md). + +1. Create a folder called `mods` that lives alongside where you would normally start the server process. +2. Add your mod files as a sub-directory of `mods`. For example if the mod name is `decay`, you'd place it in `mods/decay`. +3. Define the `GAME` environment variable for your mod name. The dedicated server client will use this to ensure that it starts a server for the correct mod, which corresponds with the directory name that was just created. + +```bash +export GAME=decay +``` + +4. Start the image as you normally would, either with `docker run` or `docker compose up`. Most Half-Life mods require specific startup arguments. For more details, refer to the [Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server) and the instructions for the mod you're trying to run. + +> [!TIP] +> When using a pre-built image, you'll likely want to use the `valve` image (`jives/hlds:valve`), but this ultimately depends on the mod. diff --git a/docs/SERVER_CONFIGS_AND_PLUGINS.md b/docs/SERVER_CONFIGS_AND_PLUGINS.md new file mode 100644 index 0000000..f617971 --- /dev/null +++ b/docs/SERVER_CONFIGS_AND_PLUGINS.md @@ -0,0 +1,17 @@ +# Configs and Plugins + +If you wish to add server configurations, such as add-ons, plugins, map rotations, etc, you can add them to the `config` directory. + +> [!NOTE] +> The startup examples posted in the project README already have this directory volume mapped accordingly. If you've strayed from the suggested setup, [please refer back to it to get started](../README.md). + +Any configuration files will be copied into the container on start from the `config` directory and placed within the folder for the specified game. For example, if you set the game as `cstrike`, the contents of the `config` folder will be placed within the `cstrike` directory on the server. + +> [!TIP] +> As an example if you have `config/mapcycle.txt`, on the server that will be placed in the `hlds/cstrike/mapcycle.txt` directory which is where the Half-Life Dedicated Server client expects these types of files to be placed. You can use this to install server plugins such as AMX Mod, Meta Mod, etc, as the directory can handle nested folders too, for example these can be placed in `config/addons/amxmodx` etc. + +1. Create a folder called `config` that lives alongside where you would typically start the server process. +2. Add your config files to the directory. +3. Start the image as you normally would, either with `docker run` or `docker compose up`. + +For a list of all the available server configuration types, [refer to the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Main_Page).