mirror of
https://ceregatti.org/git/daniel/dayzdockerserver.git
synced 2025-05-06 14:21:18 +00:00
There are no mpmissions in the server container when it starts for the first time. Ensure Chernarus is copied over as a default when this is detected, as the server is expected to start successfully. Presumes a default config where the map hasn't been changed.
Make development work by setting an environment variable. Set the web container to restart instead of not, should the express server crash. Copy XML files that are merged when the server starts only when the mpmissions directory exists. Refactor XML functions for better naming. Handle display of lists when no mods are installed. Add support for adding mpmissions for Deer Isle and mpmissions in general via mod integrations. Add support for Red Falcon Watercraft XML files. WIP. Add a deer isle DayZ bicycle spawn file.
This commit is contained in:
parent
5db38636c4
commit
887374587d
7 changed files with 102 additions and 75 deletions
|
@ -32,7 +32,7 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- "8001:8001/tcp"
|
- "8001:8001/tcp"
|
||||||
- "8000:8000/tcp"
|
- "8000:8000/tcp"
|
||||||
restart: no
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
# The use of the Steam API in the (very incomplete) web app requires a key. Get yours here: https://steamcommunity.com/dev/apikey
|
# The use of the Steam API in the (very incomplete) web app requires a key. Get yours here: https://steamcommunity.com/dev/apikey
|
||||||
- STEAMAPIKEY=YOUR_STEAM_API_KEY_HERE
|
- STEAMAPIKEY=YOUR_STEAM_API_KEY_HERE
|
||||||
|
@ -63,11 +63,15 @@ services:
|
||||||
# - 27016:27016/udp
|
# - 27016:27016/udp
|
||||||
# Always restart, unless stopped
|
# Always restart, unless stopped
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
# To prevent the server from starting to allow for development, set this to 1
|
||||||
|
- DEVELOPMENT=0
|
||||||
# Allows attaching a debugger from the host
|
# Allows attaching a debugger from the host
|
||||||
cap_add:
|
# cap_add:
|
||||||
- SYS_PTRACE
|
# - SYS_PTRACE
|
||||||
# Allows core files to be created within the container. These are VERY LARGE! Enable only for debugging!
|
# Allows core files to be created within the container. These are VERY LARGE! Enable only for debugging!
|
||||||
ulimits:
|
# One must also set the sysctl kernel.core_pattern parameter ON THE HOST to a path that is writable within the container. YMMV
|
||||||
core:
|
# ulimits:
|
||||||
soft: -1
|
# core:
|
||||||
hard: -1
|
# soft: -1
|
||||||
|
# hard: -1
|
||||||
|
|
|
@ -67,15 +67,20 @@ prompt_yn(){
|
||||||
# List mods
|
# List mods
|
||||||
list(){
|
list(){
|
||||||
X=1
|
X=1
|
||||||
C="${green}"
|
C="${green}"
|
||||||
spaces=" "
|
spaces=" "
|
||||||
echo
|
FIRST=1
|
||||||
echo -e " ID Name URL Size"
|
for link in $(ls -d ${SERVER_FILES}/@* 2> /dev/null | sort)
|
||||||
echo "------------------------------------------------------------------------------------------------------------------------"
|
do
|
||||||
for link in $(ls -d ${SERVER_FILES}/@* | sort)
|
if [[ ${FIRST} = 1 ]]
|
||||||
do
|
then
|
||||||
|
echo
|
||||||
|
echo -e " ID Name URL Size"
|
||||||
|
echo "------------------------------------------------------------------------------------------------------------------------"
|
||||||
|
FIRST=0
|
||||||
|
fi
|
||||||
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
||||||
MODNAME=$(get_mod_name ${ID})
|
MODNAME=$(get_mod_name ${ID})
|
||||||
SIZE=$(du -sh "${WORKSHOP_DIR}/${ID}" | awk '{print $1}')
|
SIZE=$(du -sh "${WORKSHOP_DIR}/${ID}" | awk '{print $1}')
|
||||||
printf "${C}%.3d %s %.30s %s https://steamcommunity.com/sharedfiles/filedetails/?id=%s %s${default}\n" ${X} ${ID} "${MODNAME}" "${spaces:${#MODNAME}+1}" ${ID} ${SIZE}
|
printf "${C}%.3d %s %.30s %s https://steamcommunity.com/sharedfiles/filedetails/?id=%s %s${default}\n" ${X} ${ID} "${MODNAME}" "${spaces:${#MODNAME}+1}" ${ID} ${SIZE}
|
||||||
X=$((X+1))
|
X=$((X+1))
|
||||||
|
@ -102,19 +107,19 @@ get_mod_id(){
|
||||||
echo -n ${1}
|
echo -n ${1}
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
# If we have a second argument, we want to iterate over active server mods
|
# If we have a second argument, we want to iterate over active server mods
|
||||||
DIR=${SERVER_FILES}
|
DIR=${SERVER_FILES}
|
||||||
ARG="-d"
|
ARG="-d"
|
||||||
if [[ ${2} = "0" ]]
|
if [[ ${2} = "0" ]]
|
||||||
then
|
then
|
||||||
ARG="-tdr"
|
ARG="-tdr"
|
||||||
DIR=${SERVER_PROFILE}
|
DIR=${SERVER_PROFILE}
|
||||||
fi
|
fi
|
||||||
# echo "DIR: ${DIR}, ARG: ${ARG}" >&2
|
# echo "DIR: ${DIR}, ARG: ${ARG}" >&2
|
||||||
X=1
|
X=1
|
||||||
# Loop over mods
|
# Loop over mods
|
||||||
for link in $(ls ${ARG} ${DIR}/@* 2> /dev/null)
|
for link in $(ls ${ARG} ${DIR}/@* 2> /dev/null)
|
||||||
do
|
do
|
||||||
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
||||||
if [[ ${X} = ${1} ]]
|
if [[ ${X} = ${1} ]]
|
||||||
then
|
then
|
||||||
|
@ -127,27 +132,27 @@ get_mod_id(){
|
||||||
|
|
||||||
get_mods(){
|
get_mods(){
|
||||||
workshoplist=""
|
workshoplist=""
|
||||||
for link in $(ls -d ${SERVER_FILES}/@* 2> /dev/null | sort)
|
for link in $(ls -d ${SERVER_FILES}/@* 2> /dev/null | sort)
|
||||||
do
|
do
|
||||||
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
||||||
MODNAME=$(get_mod_name ${ID})
|
MODNAME=$(get_mod_name ${ID})
|
||||||
workshoplist+=" +workshop_download_item "${release_client_appid}" "${ID}
|
workshoplist+=" +workshop_download_item "${release_client_appid}" "${ID}
|
||||||
done
|
done
|
||||||
get_mod_command_line
|
get_mod_command_line
|
||||||
}
|
}
|
||||||
|
|
||||||
get_mod_command_line(){
|
get_mod_command_line(){
|
||||||
mod_command_line=""
|
mod_command_line=""
|
||||||
for link in $(ls -tdr ${SERVER_PROFILE}/@* 2> /dev/null)
|
for link in $(ls -tdr ${SERVER_PROFILE}/@* 2> /dev/null)
|
||||||
do
|
do
|
||||||
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
||||||
MODNAME=$(get_mod_name ${ID})
|
MODNAME=$(get_mod_name ${ID})
|
||||||
mod_command_line+="@${MODNAME};"
|
mod_command_line+="@${MODNAME};"
|
||||||
done
|
done
|
||||||
if [[ ${mod_command_line} != "" ]]
|
if [[ ${mod_command_line} != "" ]]
|
||||||
then
|
then
|
||||||
mod_command_line='-mod='${mod_command_line::-1}
|
mod_command_line='-mod='${mod_command_line::-1}
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Copy mod keys
|
# Copy mod keys
|
||||||
|
|
|
@ -2,27 +2,27 @@
|
||||||
|
|
||||||
set -eE
|
set -eE
|
||||||
|
|
||||||
source /files/mods/${1}/install.env
|
if [ -f /files/mods/${1}/install.env ]
|
||||||
|
then
|
||||||
|
source /files/mods/${1}/install.env
|
||||||
|
else
|
||||||
|
echo "install.env not found for mod id ${1}..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
|
||||||
if [[ ${2} = "uninstall" ]]
|
if [[ ${2} = "uninstall" ]]
|
||||||
then
|
then
|
||||||
echo "Backing up, as uninstalling will remove the ${MAP} mpmissions directory"
|
echo "Backing up, as uninstalling will remove the ${MAP} mpmissions directory"
|
||||||
dayzserver backup
|
dz backup
|
||||||
echo "Uninstalling mpmissions..."
|
|
||||||
echo
|
|
||||||
rm -rf ${SERVER_FILES}/mpmissions/${MPDIR}
|
rm -rf ${SERVER_FILES}/mpmissions/${MPDIR}
|
||||||
elif [[ ${2} = "update" ]]
|
elif [[ ${2} = "update" ]]
|
||||||
then
|
then
|
||||||
echo "Updating mpmissions directory..."
|
|
||||||
echo
|
|
||||||
cd /tmp
|
cd /tmp
|
||||||
git clone ${REPO} 2> /dev/null 1> /dev/null
|
git clone ${REPO} 2> /dev/null 1> /dev/null
|
||||||
cp -a ${DIR}/${MPDIR} ${SERVER_FILES}/mpmissions
|
cp -a ${DIR}/${MPDIR} ${SERVER_FILES}/mpmissions
|
||||||
rm -rf ${DIR}
|
rm -rf ${DIR}
|
||||||
else
|
elif [[ ${2} = "install" ]]
|
||||||
echo "Installing mpmissions files..."
|
then
|
||||||
echo
|
|
||||||
cd /tmp
|
cd /tmp
|
||||||
git clone ${REPO} 2> /dev/null 1> /dev/null
|
git clone ${REPO} 2> /dev/null 1> /dev/null
|
||||||
cp -a ${DIR}/${MPDIR} ${SERVER_FILES}/mpmissions
|
cp -a ${DIR}/${MPDIR} ${SERVER_FILES}/mpmissions
|
||||||
|
|
|
@ -7,6 +7,11 @@ set -eE
|
||||||
|
|
||||||
ID=${1}
|
ID=${1}
|
||||||
|
|
||||||
|
if ! [ -f ${FILES}/mods/${ID}/xml.env ]
|
||||||
|
then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
source ${FILES}/mods/${ID}/xml.env
|
source ${FILES}/mods/${ID}/xml.env
|
||||||
|
|
||||||
# Iterate over the file names we can handle
|
# Iterate over the file names we can handle
|
||||||
|
|
|
@ -126,15 +126,21 @@ report() {
|
||||||
|
|
||||||
mergexml(){
|
mergexml(){
|
||||||
# First copy the pristine files from upstream
|
# First copy the pristine files from upstream
|
||||||
echo "Copying pristine versions of cfgeconomycore.xml and cfgeventspawns.xml..."
|
for i in cfgeconomycore.xml #cfgeventspawns.xml
|
||||||
find /mpmissions -name cfgeconomycore.xml -exec cp -v {} ${SERVER_FILES}{} \;
|
do
|
||||||
# find /mpmissions -name cfgeventspawns.xml -exec cp {} ${SERVER_FILES}{} \;
|
echo "Copying pristine version of ${i} into local mpmission(s)..."
|
||||||
|
for dir in $(ls -d ${MPMISSIONS}/*)
|
||||||
|
do
|
||||||
|
#echo "dir: ${dir}, basename: $(basename ${dir})"
|
||||||
|
find /mpmissions/$(basename ${dir}) -name ${i} -exec cp -v {} ${SERVER_FILES}{} \;
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
# Follow https://community.bistudio.com/wiki/DayZ:Central_Economy_mission_files_modding and make a single XML
|
# Follow https://community.bistudio.com/wiki/DayZ:Central_Economy_mission_files_modding and make a single XML
|
||||||
# file for the ones that can go into it.
|
# file for the ones that can go into it.
|
||||||
for link in $(ls -tdr ${SERVER_PROFILE}/@* 2> /dev/null)
|
for link in $(ls -tdr ${SERVER_PROFILE}/@* 2> /dev/null)
|
||||||
do
|
do
|
||||||
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
ID=$(readlink ${link} | awk -F/ '{print $NF}')
|
||||||
# Going to have to maintain a matrix of file names -> root node -> child node permutations
|
# Going to have to maintain a matrix of file names -> root node -> child node permutations
|
||||||
C=""
|
C=""
|
||||||
for i in "CFGSPAWNABLETYPES:spawnabletypes:type" "EVENTS:events:event" "TYPES:types:type"
|
for i in "CFGSPAWNABLETYPES:spawnabletypes:type" "EVENTS:events:event" "TYPES:types:type"
|
||||||
|
@ -180,13 +186,20 @@ mergexml(){
|
||||||
|
|
||||||
# Start the server in the foreground
|
# Start the server in the foreground
|
||||||
start(){
|
start(){
|
||||||
# Ensure mpmissions has at least one map. If not, block the server from starting
|
# Ensure mpmissions has at least one map. If not, copy it from the local read-only volume that stores pristine mpmissons directories
|
||||||
if [ ! -d "${MPMISSIONS}/dayzOffline.chernarusplus" ]
|
if [ ! -d "${MPMISSIONS}/dayzOffline.chernarusplus" ]
|
||||||
then
|
then
|
||||||
echo
|
echo
|
||||||
echo "Performing one-time copy of Chernarus mpmissions..."
|
echo "Performing one-time copy of Chernarus mpmissions..."
|
||||||
echo
|
echo
|
||||||
cp -a /mpmission/dayzOffline.chernarusplus ${MPMISSIONS}
|
cp -av /mpmissions/dayzOffline.chernarusplus ${MPMISSIONS}
|
||||||
|
fi
|
||||||
|
# If we're developing, just block the container
|
||||||
|
if [[ ${DEVELOPMENT} = "1" ]]
|
||||||
|
then
|
||||||
|
echo "DEVELOPMENT mode, blocking..."
|
||||||
|
tail -f /dev/null
|
||||||
|
exit 0
|
||||||
fi
|
fi
|
||||||
# Do the report on exit. Set here so that it only happens once we're starting the server, and not for other actions.
|
# Do the report on exit. Set here so that it only happens once we're starting the server, and not for other actions.
|
||||||
trap '
|
trap '
|
||||||
|
@ -422,9 +435,6 @@ case "${C}" in
|
||||||
n|rcon)
|
n|rcon)
|
||||||
rcon "${@}"
|
rcon "${@}"
|
||||||
;;
|
;;
|
||||||
r|remove)
|
|
||||||
remove "${@}"
|
|
||||||
;;
|
|
||||||
r|restart)
|
r|restart)
|
||||||
restart "${@}"
|
restart "${@}"
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Set PS1 so we know we're in the container
|
# Set PS1 so we know we're in the container, should we exec into it.
|
||||||
cat > .bashrc <<EOF
|
cat > .bashrc <<EOF
|
||||||
alias ls='ls --color'
|
alias ls='ls --color'
|
||||||
export PS1="${debian_chroot:+($debian_chroot)}\u@dz-server:\w\$ "
|
export PS1="${debian_chroot:+($debian_chroot)}\u@dz-server:\w\$ "
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Uncomment the line below to run things manually in the container, then run:
|
# Start the server.
|
||||||
# docker compose exec main bash, and from within the container: dz start (or do whatever)
|
# If the DEVELOPMENT environment variable is set to 1, the container will just block and not start the server.
|
||||||
#tail -f /dev/null
|
|
||||||
|
|
||||||
# Otherwise, start the server normally
|
|
||||||
dz start
|
dz start
|
||||||
|
|
30
web/bin/dz
30
web/bin/dz
|
@ -26,6 +26,7 @@ Options and arguments:
|
||||||
i|install - Install the DayZ server files
|
i|install - Install the DayZ server files
|
||||||
g|login - Login to Steam.
|
g|login - Login to Steam.
|
||||||
m|modupdate - Update the mod files
|
m|modupdate - Update the mod files
|
||||||
|
p|map id - Install a mod's mpmissions files by id. (Presumes template exists)
|
||||||
r|remove id - Remove all files and directories of a Workshop item by id
|
r|remove id - Remove all files and directories of a Workshop item by id
|
||||||
s|status - Shows Steam login status, if base files are installed, installed mods
|
s|status - Shows Steam login status, if base files are installed, installed mods
|
||||||
u|update - Update the server files
|
u|update - Update the server files
|
||||||
|
@ -110,7 +111,7 @@ add(){
|
||||||
# Lower case all the files in mod directories.
|
# Lower case all the files in mod directories.
|
||||||
find "${WORKSHOP_DIR}/${1}" -depth -exec rename -f 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
|
find "${WORKSHOP_DIR}/${1}" -depth -exec rename -f 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
|
||||||
echo -e "Mod id ${1} - ${green}${MODNAME}${default} - added"
|
echo -e "Mod id ${1} - ${green}${MODNAME}${default} - added"
|
||||||
installxml ${ID}
|
xml ${ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Remove a mod
|
# Remove a mod
|
||||||
|
@ -241,7 +242,6 @@ modupdate(){
|
||||||
status(){
|
status(){
|
||||||
INSTALLED="${NO}"
|
INSTALLED="${NO}"
|
||||||
LOGGED_IN="${NO}"
|
LOGGED_IN="${NO}"
|
||||||
RUNNING="${NO}"
|
|
||||||
|
|
||||||
# DayZ Server files installation
|
# DayZ Server files installation
|
||||||
if [ -f "${SERVER_INSTALL_FILE}" ]
|
if [ -f "${SERVER_INSTALL_FILE}" ]
|
||||||
|
@ -274,31 +274,34 @@ Mods: "
|
||||||
MODS=$(list)
|
MODS=$(list)
|
||||||
if [[ ${MODS} == "" ]]
|
if [[ ${MODS} == "" ]]
|
||||||
then
|
then
|
||||||
echo -n "none"
|
echo -ne "${red}none${default}"
|
||||||
fi
|
fi
|
||||||
echo -e "${MODS}"
|
echo -e "${MODS}"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_mod_install(){
|
map(){
|
||||||
# See if this mod id exists in files/mods, and offer to install other server side files if an install.sh is found
|
# Install map mpmissions for mods that have them. Presumes a map.env was created for the mod, with the required metadata (git URL, etc.)
|
||||||
|
if [ -f ${FILES}/mods/${1}/install.env ]
|
||||||
|
then
|
||||||
|
echo "Installing mpmissions files for mod id ${1}..."
|
||||||
|
source ${FILES}/mods/${1}/install.env
|
||||||
|
${FILES}/bin/install.sh ${1} install
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
mod_install(){
|
||||||
if [ -f ${FILES}/mods/${1}/${2}.sh ]
|
if [ -f ${FILES}/mods/${1}/${2}.sh ]
|
||||||
then
|
then
|
||||||
echo "An ${2}.sh was found for mod id ${1}. Running..."
|
echo "An ${2}.sh was found for mod id ${1}. Running..."
|
||||||
${FILES}/mods/${1}/${2}.sh
|
${FILES}/mods/${1}/${2}.sh
|
||||||
fi
|
fi
|
||||||
# A generic map install script. Presumes a git repo as the source
|
# A generic map install script. Presumes a git repo as the source
|
||||||
if [ -f ${FILES}/mods/${1}/install.env ]
|
|
||||||
then
|
|
||||||
echo "An ${2}.env was found for mod id ${1}. Performing ${2}..."
|
|
||||||
source ${FILES}/mods/${1}/install.env
|
|
||||||
${FILES}/mods/install.sh ${1} ${2}
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# "Manage" XML files.
|
# "Manage" XML files.
|
||||||
xml(){
|
xml(){
|
||||||
/files/bin/xml.sh ${1}
|
/files/bin/xml.sh ${1}
|
||||||
installxml ${1}
|
#installxml ${1}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Capture the first argument and shift it off so we can pass $@ to every function
|
# Capture the first argument and shift it off so we can pass $@ to every function
|
||||||
|
@ -326,6 +329,9 @@ case "${C}" in
|
||||||
l|s|status)
|
l|s|status)
|
||||||
status "${@}"
|
status "${@}"
|
||||||
;;
|
;;
|
||||||
|
p|map)
|
||||||
|
map "${@}"
|
||||||
|
;;
|
||||||
u|update)
|
u|update)
|
||||||
update "${@}"
|
update "${@}"
|
||||||
;;
|
;;
|
||||||
|
|
Loading…
Add table
Reference in a new issue