diff --git a/Dockerfile b/Dockerfile index 7210c87..4fc816f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,6 +40,7 @@ ENV ARMA_PROFILE=/home/profile ENV ARMA_BINARY="./ArmaReforgerServer" ENV ARMA_PARAMS="" ENV ARMA_MAX_FPS=120 +ENV ARMA_WORKSHOP_DIR=/reforger/workshop ENV SERVER_BIND_ADDRESS="0.0.0.0" ENV SERVER_BIND_PORT=2001 @@ -61,6 +62,8 @@ ENV GAME_PROPS_FAST_VALIDATION=true ENV GAME_PROPS_SERVER_MAX_VIEW_DISTANCE=2500 ENV GAME_PROPS_SERVER_MIN_GRASS_DISTANCE=50 ENV GAME_PROPS_NETWORK_VIEW_DISTANCE=1000 +ENV GAME_MODS_IDS_LIST="" +ENV GAME_MODS_JSON_FILE_PATH="" ENV SKIP_INSTALL=false @@ -69,6 +72,7 @@ WORKDIR /reforger VOLUME /steamcmd VOLUME /home/profile VOLUME /reforger/Configs +VOLUME /reforger/workshop EXPOSE 2001/udp EXPOSE 17777/udp diff --git a/README.md b/README.md index 0946ab2..a70256e 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ An Arma Reforger dedicated server. Updates to the latest version every time it i -p 2001:2001/udp \ -v path/to/configs:/reforger/Configs \ -v path/to/profiles:/home/profile \ + -v path/to/workshop:/reforger/workshop \ -e SERVER_REGION="EU" \ -e SERVER_HOST_REGISTER_ADDRESS="public ip" \ -e GAME_NAME="My Docker Reforger Server" \ @@ -26,7 +27,7 @@ Simply check-out / copy [the provided docker-compose.yml](docker-compose.yml) an ## Parameters -Check [the Dockerfile](Dockerfile#L32-L64), more docs will come later. +Check [the Dockerfile](Dockerfile#L32-L67), more docs will come later. ### Configs @@ -37,3 +38,33 @@ Alternatively, change the `ARMA_CONFIG` variable to a file present in the `Confi ### Experimental server To use the experimental server instead of the regular set `STEAM_APPID` variable to `1890870`. + +### Mods + +Workshop mods can be defined in two ways. You can use both or either of those. + +#### GAME_MODS_IDS_LIST + +A comma separated list of IDs, with an optional version. + +```sh +-e GAME_MODS_IDS_LIST="5965770215E93269=1.0.6,5965550F24A0C152" +``` + +#### GAME_MODS_JSON_FILE_PATH + +Path to a JSON file that contains array of mod objects. + +```sh +-v ${PWD}/mods_file.json:/mods_file.json +-e GAME_MODS_JSON_FILE_PATH="/mods_file.json" +``` + +```json +[ + { + "modId": "597706449575D90B", + "version": "1.1.1" + } +] +``` diff --git a/docker-compose.yml b/docker-compose.yml index ebdf54b..ada8203 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,7 @@ services: volumes: - ./reforger/configs:/reforger/Configs - ./reforger/profile:/home/profile + - ./reforger/workshop:/reforger/workshop environment: - SERVER_PUBLIC_ADDRESS=public-ip - GAME_NAME=My Docker Reforger Server diff --git a/launch.py b/launch.py index 835d150..052b661 100644 --- a/launch.py +++ b/launch.py @@ -1,6 +1,7 @@ import json import os import random +import re import subprocess CONFIG_GENERATED = "/reforger/Configs/docker_generated.json" @@ -112,6 +113,38 @@ def bool_str(text): config["game"]["gameProperties"]["networkViewDistance"] = int( os.environ["GAME_PROPS_NETWORK_VIEW_DISTANCE"] ) + if env_defined("GAME_MODS_IDS_LIST"): + reg = re.compile(r"^[A-Z\d,=.]+$") + assert reg.match( + str(os.environ["GAME_MODS_IDS_LIST"]) + ), "Illegal characters in GAME_MODS_IDS_LIST env" + mods = str(os.environ["GAME_MODS_IDS_LIST"]).split(",") + mods[:] = [mod for mod in mods if mod] # Remove empty items form list + reg = re.compile(r"^\d\.\d\.\d$") + for mod in mods: + mod_details = mod.split("=") + assert 0 < len(mod_details) < 3, f"{mod} mod not defined properly" + mod_config = {"modId": mod_details[0]} + if len(mod_details) == 2: + assert reg.match( + mod_details[1] + ), f"{mod} mod version does not match the pattern" + mod_config["version"] = mod_details[1] + config["game"]["mods"].append(mod_config) + if env_defined("GAME_MODS_JSON_FILE_PATH"): + with open(os.environ["GAME_MODS_JSON_FILE_PATH"]) as f: + json_mods = json.load(f) + allowed_keys = ["modId", "name", "version"] + for provided_mod in json_mods: + assert ( + "modId" in provided_mod + ), f"Entry in GAME_MODS_JSON_FILE_PATH file does not contain modId: {provided_mod}" + valid_mod = { + key: provided_mod[key] + for key in allowed_keys + if key in provided_mod + } # Extract only valid config keys + config["game"]["mods"].append(valid_mod) f = open(CONFIG_GENERATED, "w") json.dump(config, f, indent=4) @@ -127,6 +160,8 @@ def bool_str(text): "-nothrow", f"-maxFPS {os.environ['ARMA_MAX_FPS']}", f"-profile {os.environ['ARMA_PROFILE']}", + f"-addonDownloadDir {os.environ['ARMA_WORKSHOP_DIR']}", + f"-addonsDir {os.environ['ARMA_WORKSHOP_DIR']}", os.environ["ARMA_PARAMS"], ] )