From a34057a89a76f5b42410b3fea44f523a7f720f02 Mon Sep 17 00:00:00 2001 From: GenZmeY Date: Thu, 9 Jul 2020 01:59:33 +0300 Subject: [PATCH] Wed May 27 2020 --- SOURCES/kf2-srv | 476 ++++++++++++++++++++++++++-------- SOURCES/kf2-srv-beta@.service | 2 +- SOURCES/kf2-srv.conf | 20 +- SOURCES/kf2-srv@.service | 2 +- SOURCES/main.conf.template | 25 +- SPECS/kf2-srv.spec | 35 ++- 6 files changed, 430 insertions(+), 130 deletions(-) mode change 100644 => 100755 SOURCES/kf2-srv.conf diff --git a/SOURCES/kf2-srv b/SOURCES/kf2-srv index ebc7c61..3595548 100755 --- a/SOURCES/kf2-srv +++ b/SOURCES/kf2-srv @@ -17,24 +17,22 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +declare -a DiffArray +declare -a WaveArray +declare -A ModeArray + source /etc/steamcmd/steamcmd.conf +source /etc/kf2-srv/kf2-srv.conf ScriptFullname=$(readlink -e "$0") ScriptName=$(echo "$ScriptFullname" | awk -F '/' '{print $NF;}') -ScriptVersion="0.8.0" +ScriptVersion="0.9.0" +# Constants. Don't change. AppServerNum="232130" AppClientNum="232090" StrangeConstUID="17825793" - -DiffArray=('Normal' 'Hard' 'Suicide' 'Hell') -WaveArray=('4' '7' '10') -declare -A ModeArray -ModeArray['KFGameContent.KFGameInfo_Survival']='Survival' -ModeArray['KFGameContent.KFGameInfo_WeeklySurvival']='Weekly' -ModeArray['KFGameContent.KFGameInfo_Endless']='Endless' -ModeArray['KFGameContent.KFGameInfo_Objective']='Objective' -ModeArray['KFGameContent.KFGameInfo_VersusSurvival']='Versus' +ServerBotLogin="srvbot" function show_help () { @@ -59,6 +57,7 @@ function show_help () echo " необходимости перекачивает их." echo " -r, --run [OPTIONS] запускает экземпляр сервера с указанными" echo " ПАРАМЕТРАМИ" + echo " -c, --chat MSG [INSTANCE] отправляет сообщение в чат указанных экземпляров" echo " -st, --start [INSTANCE] запускает указанный ЭКЗЕМПЛЯР сервера; если" echo " ЭКЗЕМПЛЯР не указан, запускает все" echo " автозапускаемые экземпляры сервера" @@ -98,9 +97,13 @@ function show_help () echo " -bd, --ban-del [BAN_ID] удаляет пользователя из списка заблокированных" echo " допустимо использовать ID3, SteamID, а также" echo " ссылку на профиль пользователя" + echo " -fp, --fix-permissions [INSTANCE] поправить права на ini файлы" + echo " -as, --admin-sync синхронизировать всех админов (заглушка)" + echo " -pg, --password-game PASSWORD [INSTANCE] установить пароль игры для экземпляров" + echo " -pa, --password-admin PASSWORD [INSTANCE] установить пароль админа для экземпляров" echo " -h, --help display this help and exit" } - + # Use this function with non-root user only!!! function run_as_root () # $*: Args { @@ -198,9 +201,9 @@ function new_instance () # $*: InstanceName[s] for Instance in $(show_instances) do local Config="$InstanceConfigDir/$Instance/main.conf" - local GamePort=$(grep -Po '"-port=([0-9]+)' "$Config" | grep -Po '[0-9]+$') - local WebAdminPort=$(grep -Po '"-webadminport=([0-9]+)' "$Config" | grep -Po '[0-9]+$') - local QueryPort=$(grep -Po '"-queryport=([0-9]+)' "$Config" | grep -Po '[0-9]+$') + local GamePort=$(multini --get "$Config" '' 'PortGame') + local WebAdminPort=$(multini --get "$Config" '' 'PortWeb') + local QueryPort=$(multini --get "$Config" '' 'PortQuery') if [[ "$GamePort" -gt "$MaxGamePort" ]]; then MaxGamePort="$GamePort"; fi if [[ "$QueryPort" -gt "$MaxQueryPort" ]]; then MaxQueryPort="$QueryPort"; fi if [[ "$WebAdminPort" -gt "$MaxWebAdminPort" ]]; then MaxWebAdminPort="$WebAdminPort"; fi @@ -224,6 +227,8 @@ function new_instance () # $*: InstanceName[s] install $FileMode "$MainConfigTemplate" "$InstanceDir/main.conf" install $FileMode "$DefaultConfigDir/KFAI.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/KFWeb.ini" "$InstanceDir" + install $FileMode "$DefaultConfigDir/KFWebAdmin.ini" "$InstanceDir" + install $FileMode "$DefaultConfigDir/KFMultiAdmin.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/LinuxServer-KFEngine.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/LinuxServer-KFGame.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/LinuxServer-KFInput.ini" "$InstanceDir" @@ -235,9 +240,9 @@ function new_instance () # $*: InstanceName[s] ((MaxGamePort++)); ((MaxQueryPort++)); ((MaxWebAdminPort++)) - sed -i -r --follow-symlinks "s/-port=[0-9]+/-port=$MaxGamePort/g" "$InstanceDir/main.conf" - sed -i -r --follow-symlinks "s/-queryport=[0-9]+/-queryport=$MaxQueryPort/g" "$InstanceDir/main.conf" - sed -i -r --follow-symlinks "s/-webadminport=[0-9]+/-webadminport=$MaxWebAdminPort/g" "$InstanceDir/main.conf" + multini -s "$InstanceDir/main.conf" '' 'PortGame' "$MaxGamePort" + multini -s "$InstanceDir/main.conf" '' 'PortQuery' "$MaxQueryPort" + multini -s "$InstanceDir/main.conf" '' 'PortWeb' "$MaxWebAdminPort" echo "Instance $Instance created. See /etc/$ScriptName/instances$BetaPostfix/$Instance for edit configuration" done @@ -286,31 +291,37 @@ function show_status_implementation_body () # $*: [InstanceName[s]] local IsRuning="stopped" fi - local Description=$(grep -P 'Description=' "$InstanceConfigDir/$Instance/main.conf" | sed -r 's/(Description=|")//g') - local GamePort=$(grep -Po '"-port=([0-9]+)' "$InstanceConfigDir/$Instance/main.conf" | grep -Po '[0-9]+$') - local WebAdminPort=$(grep -Po '"-webadminport=([0-9]+)' "$InstanceConfigDir/$Instance/main.conf" | grep -Po '[0-9]+$') - local QueryPort=$(grep -Po '"-queryport=([0-9]+)' "$InstanceConfigDir/$Instance/main.conf" | grep -Po '[0-9]+$') - local GameType=$(grep -Po 'Game=([^\?]+)' "$InstanceConfigDir/$Instance/main.conf" | sed -r 's/Game=([^?]+)/\1/g' ) - local GameLength=$(grep -Po 'GameLength=([0-9]+)' "$InstanceConfigDir/$Instance/main.conf" | grep -Po '[0-9]+$') - local GameDifficulty=$(grep -Po 'Difficulty=([0-9]+)' "$InstanceConfigDir/$Instance/main.conf" | grep -Po '[0-9]+$') + local Comment=$( multini -g "$InstanceConfigDir/$Instance/main.conf" '' "Comment") + local GamePort=$( multini -g "$InstanceConfigDir/$Instance/main.conf" '' "PortGame") + local WebAdminPort=$( multini -g "$InstanceConfigDir/$Instance/main.conf" '' "PortWeb") + local QueryPort=$( multini -g "$InstanceConfigDir/$Instance/main.conf" '' "PortQuery") + local GameType=$( multini -g "$InstanceConfigDir/$Instance/main.conf" '' "Game") + local GameLength=$( multini -g "$InstanceConfigDir/$Instance/main.conf" '' "Length") + local GameDifficulty=$( multini -g "$InstanceConfigDir/$Instance/main.conf" '' "Difficulty") + local Map=$( multini -g "$InstanceConfigDir/$Instance/main.conf" '' "Map") + local Args=$( multini -g "$InstanceConfigDir/$Instance/main.conf" '' "Args") local DisplayGameType=${ModeArray[$GameType]} local DisplayGameLength=${WaveArray[$GameLength]} local DisplayDifficulty=${DiffArray[$GameDifficulty]} - if [[ "$DisplayGameType" == 'Weekly' || \ - "$DisplayGameType" == 'Endless' || \ - "$DisplayGameType" == 'Versus' || \ - "$DisplayGameType" == 'Objective' ]]; then + if [[ -z "$DisplayGameType" ]]; then + DisplayGameType="$GameType" + fi + + if [[ "$GameType" == 'KFGameContent.KFGameInfo_WeeklySurvival' || \ + "$GameType" == 'KFGameContent.KFGameInfo_Endless' || \ + "$GameType" == 'KFGameContent.KFGameInfo_VersusSurvival' || \ + "$GameType" == 'KFGameContent.KFGameInfo_Objective' ]]; then DisplayGameLength='-' fi - if [[ "$DisplayGameType" == 'Weekly' || \ - "$DisplayGameType" == 'Versus' ]]; then + if [[ "$GameType" == 'KFGameContent.KFGameInfo_WeeklySurvival' || \ + "$DisplayGameType" == 'KFGameContent.KFGameInfo_VersusSurvival' ]]; then DisplayDifficulty='-' fi - echo -e "$Instance:$IsEnabled:$IsRuning:$GamePort:$QueryPort:$WebAdminPort:$DisplayGameType:$DisplayGameLength:$DisplayDifficulty:$Description" + echo -e "$Instance:$IsEnabled:$IsRuning:$GamePort:$QueryPort:$WebAdminPort:$DisplayGameType:$DisplayGameLength:$DisplayDifficulty:$Args:$Comment" done } @@ -328,7 +339,7 @@ function show_status_implementation_full () # $*: [InstanceName[s]] done fi - echo -e "INSTANCE:AUTORUN:STATE:P_GAME:P_QUERY:P_WEB:TYPE:LEN:DIFF:DESCRIPTION" + echo -e "INSTANCE:AUTORUN:STATE:P_GAME:P_QUERY:P_WEB:TYPE:LEN:DIFF:ARGS:COMMENT" show_status_implementation_body "$InstanceList" | sort -t : -k 4 } @@ -348,33 +359,9 @@ function validate () start_instance } -function make_default_instance () +function make_default_instance () # $1: Dir { local InstanceDir="$InstanceConfigDir/default" - - chmod 664 \ - "$DefaultConfigDir/KFAI.ini" \ - "$DefaultConfigDir/KFWeb.ini" \ - "$DefaultConfigDir/LinuxServer-KFEngine.ini" \ - "$DefaultConfigDir/LinuxServer-KFGame.ini" \ - "$DefaultConfigDir/LinuxServer-KFInput.ini" \ - "$DefaultConfigDir/LinuxServer-KFSystemSettings.ini" \ - "$DefaultConfigDir/LinuxServer/LinuxServerEngine.ini" \ - "$DefaultConfigDir/LinuxServer/LinuxServerGame.ini" \ - "$DefaultConfigDir/LinuxServer/LinuxServerInput.ini" \ - "$DefaultConfigDir/LinuxServer/LinuxServerSystemSettings.ini" - - dos2unix \ - "$DefaultConfigDir/KFAI.ini" \ - "$DefaultConfigDir/KFWeb.ini" \ - "$DefaultConfigDir/LinuxServer-KFEngine.ini" \ - "$DefaultConfigDir/LinuxServer-KFGame.ini" \ - "$DefaultConfigDir/LinuxServer-KFInput.ini" \ - "$DefaultConfigDir/LinuxServer-KFSystemSettings.ini" \ - "$DefaultConfigDir/LinuxServer/LinuxServerEngine.ini" \ - "$DefaultConfigDir/LinuxServer/LinuxServerGame.ini" \ - "$DefaultConfigDir/LinuxServer/LinuxServerInput.ini" \ - "$DefaultConfigDir/LinuxServer/LinuxServerSystemSettings.ini" install -d -g "$SteamUser" -o "$SteamUser" -m 775 "$InstanceDir" install -d -g "$SteamUser" -o "$SteamUser" -m 775 "$InstanceDir/LinuxServer" @@ -382,6 +369,7 @@ function make_default_instance () ln -s "$DefaultConfigDir/KFAI.ini" "$InstanceDir/KFAI.ini" ln -s "$DefaultConfigDir/KFWeb.ini" "$InstanceDir/KFWeb.ini" ln -s "$DefaultConfigDir/KFWebAdmin.ini" "$InstanceDir/KFWebAdmin.ini" + ln -s "$DefaultConfigDir/KFMultiAdmin.ini" "$InstanceDir/KFMultiAdmin.ini" ln -s "$DefaultConfigDir/LinuxServer-KFEngine.ini" "$InstanceDir/LinuxServer-KFEngine.ini" ln -s "$DefaultConfigDir/LinuxServer-KFGame.ini" "$InstanceDir/LinuxServer-KFGame.ini" ln -s "$DefaultConfigDir/LinuxServer-KFInput.ini" "$InstanceDir/LinuxServer-KFInput.ini" @@ -390,6 +378,36 @@ function make_default_instance () ln -s "$DefaultConfigDir/LinuxServer/LinuxServerGame.ini" "$InstanceDir/LinuxServer/LinuxServerGame.ini" ln -s "$DefaultConfigDir/LinuxServer/LinuxServerInput.ini" "$InstanceDir/LinuxServer/LinuxServerInput.ini" ln -s "$DefaultConfigDir/LinuxServer/LinuxServerSystemSettings.ini" "$InstanceDir/LinuxServer/LinuxServerSystemSettings.ini" + + fix_ini_permissions "$InstanceDir" + fix_ini_eol "$InstanceDir" +} + +function fix_permissions () # $*: Instance[s] +{ + local InstanceList="$*" + if [[ -z "$InstanceList" ]] ; then + fix_ini_permissions "$InstanceConfigDir" + else + for Instance in $InstanceList + do + fix_ini_permissions "$InstanceConfigDir/$Instance" + done + fi +} + +function fix_ini_permissions () # $1: Dir +{ + find "$1" \( -type l -o -type f \) -name '*.ini' | \ + xargs --max-procs=$(nproc) -I {} \ + sh -c "chmod 664 {}; chown $SteamUser:$SteamUser {}" +} + +function fix_ini_eol () # $1: Dir +{ + find "$1" \( -type l -o -type f \) -name '*.ini' | \ + xargs --max-procs=$(nproc) -I {} \ + sh -c "dos2unix -F {}" } function fix_steamclient_so () @@ -433,44 +451,113 @@ function create_map_dirs () fi } +function first_install () +{ + # TODO: Replace killall + # kill -INT $PID? + # sudo is stopping me from knowing pid + if ! steamcmd +login $SteamLogin +force_install_dir $InstallDir +app_update $AppServerNum $BetaArg validate +exit; then + echo "Errors during installation - exit" + exit 1 + fi + + echo "Creating base ini files" + sudo -u "$SteamUser" $AppBin &> /dev/null & + while true + do + if [[ -e "$DefaultConfigDir/KFAI.ini" ]] && + [[ -e "$DefaultConfigDir/KFWeb.ini" ]] && + [[ -e "$DefaultConfigDir/LinuxServer-KFEngine.ini" ]] && + [[ -e "$DefaultConfigDir/LinuxServer-KFGame.ini" ]] && + [[ -e "$DefaultConfigDir/LinuxServer-KFInput.ini" ]] && + [[ -e "$DefaultConfigDir/LinuxServer-KFSystemSettings.ini" ]] && + [[ -e "$DefaultConfigDir/LinuxServer/LinuxServerEngine.ini" ]] && + [[ -e "$DefaultConfigDir/LinuxServer/LinuxServerGame.ini" ]] && + [[ -e "$DefaultConfigDir/LinuxServer/LinuxServerInput.ini" ]] && + [[ -e "$DefaultConfigDir/LinuxServer/LinuxServerSystemSettings.ini" ]]; then + break + fi + sleep 2 + done + killall -KILL KFGameSteamServer.bin.x86_64; sleep 1 + echo "Setting up WebAdmin" + multini -s "$DefaultConfigDir/KFWeb.ini" "IpDrv.WebServer" "bEnabled" "true" + sudo -u "$SteamUser" $AppBin &> /dev/null & + while true + do + if [[ -e "$DefaultConfigDir/KFWebAdmin.ini" ]]; then + break + fi + sleep 2 + done + killall -KILL KFGameSteamServer.bin.x86_64; sleep 1 + multini -s "$DefaultConfigDir/KFWebAdmin.ini" "WebAdmin.WebAdmin" "AuthenticationClass" "WebAdmin.MultiWebAdminAuth" + multini -s "$DefaultConfigDir/KFWebAdmin.ini" "WebAdmin.WebAdmin" "bHttpAuth" "True" + + echo "Wait while WebAdmin up" + sudo -u "$SteamUser" $AppBin &> /dev/null & + while ! curl -s -o "/dev/null" -u "Admin:Admin" "localhost:8080" + do + sleep 2 + done + echo "Setting up server bot" + + while ! curl -s -o "/dev/null" \ + -u "Admin:Admin" \ + "localhost:8080/ServerAdmin/multiadmin" \ + --request POST \ + --data adminid="$ServerBotLogin" \ + --data action="create" + do sleep 2; done + + while ! multini -gq \ + "$DefaultConfigDir/KFMultiAdmin.ini" \ + "$ServerBotLogin MultiAdminData" \ + "Password" + do sleep 2; done + + while ! curl -s -o "/dev/null" \ + -u "Admin:Admin" \ + "localhost:8080/ServerAdmin/multiadmin" \ + --request POST \ + --data adminid="$ServerBotLogin" \ + --data displayname="ServerBot" \ + --data enabled=1 \ + --data password1="$ServerBotPassword" \ + --data password2="$ServerBotPassword" \ + --data order="DenyAllow" \ + --data deny= \ + --data allow= \ + --data action="save" + do sleep 2; done + + while [[ -z $(multini -g \ + "$DefaultConfigDir/KFMultiAdmin.ini" \ + "$ServerBotLogin MultiAdminData" \ + "Password") ]] + do sleep 2; done + + killall -KILL KFGameSteamServer.bin.x86_64; sleep 1 + create_map_dirs + fix_steamclient_so + ln -s "$InstanceConfigDir" "$InstanceConfigLnk" + make_default_instance + echo "KF2 succesfully installed" +} + function update_kf2 () { if [[ -n "$BetaPostfix" ]]; then local BetaArg="-beta preview" fi - if ! server_exists; then # First install - if ! steamcmd +login $SteamLogin +force_install_dir $InstallDir +app_update $AppServerNum $BetaArg validate +exit; then - echo "Errors during installation - exit" - exit 1 - fi - sudo -u "$SteamUser" $AppBin & - while true - do - if [[ -e "$DefaultConfigDir/KFAI.ini" ]] && - [[ -e "$DefaultConfigDir/KFWeb.ini" ]] && - [[ -e "$DefaultConfigDir/LinuxServer-KFEngine.ini" ]] && - [[ -e "$DefaultConfigDir/LinuxServer-KFGame.ini" ]] && - [[ -e "$DefaultConfigDir/LinuxServer-KFInput.ini" ]] && - [[ -e "$DefaultConfigDir/LinuxServer-KFSystemSettings.ini" ]] && - [[ -e "$DefaultConfigDir/LinuxServer/LinuxServerEngine.ini" ]] && - [[ -e "$DefaultConfigDir/LinuxServer/LinuxServerGame.ini" ]] && - [[ -e "$DefaultConfigDir/LinuxServer/LinuxServerInput.ini" ]] && - [[ -e "$DefaultConfigDir/LinuxServer/LinuxServerSystemSettings.ini" ]]; then - break - fi - sleep 2 - done - killall -KILL KFGameSteamServer.bin.x86_64 - multini -s "$DefaultConfigDir/KFWeb.ini" "IpDrv.WebServer" "bEnabled" "true" - create_map_dirs - fix_steamclient_so - ln -s "$InstanceConfigDir" "$InstanceConfigLnk" - make_default_instance - echo "KF2 succesfully installed" - elif updates_aviable; then # Update + if ! server_exists; then + first_install + elif updates_aviable; then stop_instance steamcmd +login $SteamLogin +force_install_dir $InstallDir +app_update $AppServerNum $BetaArg +exit start_instance + else + echo "Server is up to date" fi } @@ -649,6 +736,7 @@ function workshop_list_full () # $1: WorkshoplistFile function workshop_list () # $1: [--human-readable] { + # TODO: Multiple *.kfm/*u in folder local WsList=$(mktemp) for Instance in $(show_instances) do @@ -723,9 +811,15 @@ function workshop_sync () { workshop_add $(workshop_list) + # TODO: Make it faster for Instance in $(show_instances) do - if instance_exists "$Instance"; then + local Service=$(service_name "$Instance") + if ! instance_exists "$Instance"; then + echo "Instance $Instance not exitst" + elif systemctl -q is-active $Service ; then + echo "Instance $Instance is running - skip." + else local Config="$InstanceConfigDir/$Instance/LinuxServer-KFGame.ini" for MapFile in $(find -L "$CacheDir" -type f -name '*.kfm' -printf "%f\n") do @@ -740,6 +834,7 @@ function workshop_sync () multini -s "$Config" "$MapName KFMapSummary" "bPlayableInObjective" "False" fi done + for MutFile in $(find -L "$CacheDir" -type f -name '*.u' -printf "%f\n") do MutName=$(echo "$MutFile" | sed -r 's|.u$||') @@ -748,8 +843,6 @@ function workshop_sync () multini -s "$Config" "$MutName KFMutatorSummary" "ClassName" "" fi done - else - echo "Instance $Instance not exitst" fi done } @@ -774,6 +867,15 @@ function map_rotate_save () # $*: Instance[s] done } +function map_rotate_to_webstring () # $1: MapRotate +{ + local RN='%0D%0A' + echo "$1" | \ + sed -r 's/^\(Maps=\("//' | \ + sed -r 's/"\)\)$//' | \ + sed "s/\",\"/${RN}/g" +} + function map_rotate_load () # $*: Instance[s] { local InstanceList="$*" @@ -783,17 +885,42 @@ function map_rotate_load () # $*: Instance[s] for Instance in $InstanceList do - if instance_exists "$Instance"; then - local Config="$InstanceConfigDir/$Instance/LinuxServer-KFGame.ini" - local MapRotate="$InstanceConfigDir/$Instance/MapRotate.ini" - if [[ -e "$MapRotate" ]]; then - sed -i --follow-symlinks -r "/(ActiveMapCycle=|GameMapCycles=)/d" "$Config" - sed -i --follow-symlinks "/\[KFGame\.KFGameInfo\]/ r $MapRotate" "$Config" - else - echo "$MapRotate not found - skip" + local Service=$(service_name "$Instance") + local MapRotate="$InstanceConfigDir/$Instance/MapRotate.ini" + if ! instance_exists "$Instance"; then + echo "Instance $Instance not exists" + elif ! [[ -e "$MapRotate" ]]; then + echo "$MapRotate not found - skip" + elif systemctl -q is-active $Service ; then + # TODO: Delete other cycles + # Example: maplistidx=1&mapcycle=KF-Airship%0D%0A&delete=doit + local ActiveCycleIndex=$(multini -g "$MapRotate" '' 'ActiveMapCycle') + local ActiveCycleWeb='' + local Index=0 + while read MapCycle + do + local MapCycleWeb=$(map_rotate_to_webstring "$MapCycle") + admin_curl "$Instance" "ServerAdmin/settings/maplist" \ + --request POST \ + --data maplistidx="$Index" \ + --data mapcycle="$MapCycleWeb" \ + --data action="save" + if [[ "$Index" -eq "$ActiveCycleIndex" ]]; then + ActiveCycleWeb="$MapCycleWeb" + fi + ((Index++)) + done < <(multini -g "$MapRotate" '' 'GameMapCycles') + if [[ -n "$ActiveCycleWeb" ]]; then + admin_curl "$Instance" "ServerAdmin/settings/maplist" \ + --request POST \ + --data maplistidx="$ActiveCycleIndex" \ + --data mapcycle="$ActiveCycleWeb" \ + --data activate="activate" fi else - echo "Instance $Instance not exitst" + local Config="$InstanceConfigDir/$Instance/LinuxServer-KFGame.ini" + sed -i --follow-symlinks -r "/(ActiveMapCycle=|GameMapCycles=)/d" "$Config" + sed -i --follow-symlinks "/\[KFGame\.KFGameInfo\]/ r $MapRotate" "$Config" fi done } @@ -821,12 +948,16 @@ function steamID64_to_steamID3 () # $1: ID4 function ban_list_ext () # $1: BanlistFile { local Num=1 - echo "NUM STEAM_ID3 STEAM_ID64 PROFILE_URL" + echo "NUM STEAM_ID3 STEAM_ID64 URL_CONST URL_EFFECTIVE" while read ID3 do local ID64=$(steamID3_to_steamID64 "$ID3") - local Url=$(curl "https://steamcommunity.com/profiles/$ID64" -s -L -I -o /dev/null -w '%{url_effective}') - echo "$Num $ID3 $ID64 $Url" + local UrlConst="https://steamcommunity.com/profiles/$ID64" + local UrlEffective=$(curl "$UrlConst" -s -L -I -o /dev/null -w '%{url_effective}') + if [[ "$UrlConst" == "$UrlEffective" ]]; then + UrlEffective="-" + fi + echo "$Num $ID3 $ID64 $UrlConst $UrlEffective" ((Num++)) done < "$1" } @@ -857,9 +988,18 @@ function ban_ID3 () # $1: ID3 do local Config="$InstanceConfigDir/$Instance/LinuxServer-KFGame.ini" local BanStr="(Uid=(A=$ID3,B=$StrangeConstUID))" + local Service=$(service_name "$Instance") if ! multini -gq "$Config" "Engine.AccessControl" "BannedIDs" "$BanStr"; then echo "Add ban $ID3 to $Instance" - multini -a "$Config" "Engine.AccessControl" "BannedIDs" "$BanStr" + if systemctl -q is-active $Service ; then + admin_curl "$Instance" "ServerAdmin/policy/bans" \ + --request POST \ + --data action="add" \ + --data steamint64=$(steamID3_to_steamID64 $ID3) \ + --data uniqueid= + else + multini -a "$Config" "Engine.AccessControl" "BannedIDs" "$BanStr" + fi fi done } @@ -871,9 +1011,18 @@ function unban_ID3 () # $1: ID3 do local Config="$InstanceConfigDir/$Instance/LinuxServer-KFGame.ini" local BanStr="(Uid=(A=$ID3,B=$StrangeConstUID))" - if multini -gq "$Config" "Engine.AccessControl" "BannedIDs" "$BanStr"; then - echo "Remove ban $ID3 from $Instance" - multini -d "$Config" "Engine.AccessControl" "BannedIDs" "$BanStr" + local Service=$(service_name "$Instance") + if systemctl -q is-active $Service ; then + echo "Instance $Instance is running - skip." + # TODO: delete ban with webadmin/curl + # POST Body example: + # banid=plainid%3A8&action=delete + # WTF is plainID?! + else + if multini -gq "$Config" "Engine.AccessControl" "BannedIDs" "$BanStr"; then + echo "Remove ban $ID3 from $Instance" + multini -d "$Config" "Engine.AccessControl" "BannedIDs" "$BanStr" + fi fi done } @@ -929,6 +1078,116 @@ function ban_sync () done } +function admin_sync () +{ + # TODO: Implementation + echo "Dummy" +} + +function admin_curl () # $1: Instance, $2: URL, $*: Request +{ + local Instance="$1" + local URL="$2" + local MainConf="$InstanceConfigDir/$Instance/main.conf" + local WebPort=$(multini --get "$MainConf" '' "PortWeb") + shift; shift + curl -s -o "/dev/null" -u "$ServerBotLogin:$ServerBotPassword" "localhost:$WebPort/$URL" $* +} + +function password_game () # $1: Password (if empty, use: ''), $*: Instance[s] +{ + if echo "$1" | grep -qP '\s'; then + echo "Password should not contain spaces" + return 1 + fi + + local Password="$1"; shift + local InstanceList="$*" + if [[ -z "$InstanceList" ]] ; then + InstanceList=$(show_instances) + fi + + for Instance in $InstanceList + do + if instance_exists "$Instance"; then + local Config="$InstanceConfigDir/$Instance/LinuxServer-KFGame.ini" + local Service=$(service_name "$Instance") + if systemctl -q is-active $Service ; then + admin_curl "$Instance" "ServerAdmin/policy/passwords" \ + --request POST \ + --data action="gamepassword" \ + --data gamepw1="$Password" \ + --data gamepw2="$Password" + else + multini -s "$Config" "Engine.AccessControl" "GamePassword" "$Password" + fi + else + echo "Instance $Instance not exitst" + fi + done +} + +function password_admin () # $1: Password (if empty, use: ''), $*: Instance[s] +{ + if echo "$1" | grep -qP '\s'; then + echo "Password should not contain spaces" + return 1 + fi + + local Password="$1"; shift + local InstanceList="$*" + if [[ -z "$InstanceList" ]] ; then + InstanceList=$(show_instances) + fi + + for Instance in $InstanceList + do + if instance_exists "$Instance"; then + local Config="$InstanceConfigDir/$Instance/LinuxServer-KFGame.ini" + local Service=$(service_name "$Instance") + if systemctl -q is-active $Service ; then + admin_curl "$Instance" "ServerAdmin/policy/passwords" \ + --request POST \ + --data action="adminpassword" \ + --data adminpw1="$Password" \ + --data adminpw2="$Password" + else + multini -s "$Config" "Engine.AccessControl" "AdminPassword" "$Password" + fi + else + echo "Instance $Instance not exitst" + fi + done +} + +function chat () +{ + local Message=$(echo "$1" | sed 's/ /+/g') + shift + local InstanceList="$*" + if [[ -z "$InstanceList" ]] ; then + InstanceList=$(show_instances) + fi + + for Instance in $InstanceList + do + if instance_exists "$Instance"; then + local Service=$(service_name "$Instance") + if systemctl -q is-active $Service ; then + admin_curl "$Instance" "ServerAdmin/current/chat+frame+data" \ + --request POST \ + --data ajax=1 \ + --data message="$Message" \ + --data teamsay=-1 + else + echo "Instance $Instance not running - skip" + fi + else + echo "Instance $Instance not exitst" + fi + done +} + if [[ "$1" == "beta" ]]; then BetaPostfix="-beta"; shift fi @@ -951,6 +1210,7 @@ case $1 in -u|--update ) if [[ "$EUID" -eq 0 ]]; then update_kf2 ; else run_as_root $*; fi ;; -v|--validate ) if [[ "$EUID" -eq 0 ]]; then validate ; else run_as_root $*; fi ;; -r|--run ) shift; run $*; ;; + -c|--chat ) shift; Msg="$1"; shift; chat "$Msg" $*; ;; -st|--start ) if [[ "$EUID" -eq 0 ]]; then shift; start_instance $*; else run_as_root $*; fi ;; -sp|--stop ) if [[ "$EUID" -eq 0 ]]; then shift; stop_instance $*; else run_as_root $*; fi ;; -rs|--restart ) if [[ "$EUID" -eq 0 ]]; then shift; restart_instance $*; else run_as_root $*; fi ;; @@ -966,5 +1226,9 @@ case $1 in -bs|--ban-sync ) if [[ "$EUID" -eq 0 ]]; then shift; ban_sync ; else run_as_root $*; fi ;; -ba|--ban-add ) if [[ "$EUID" -eq 0 ]]; then shift; ban_add $*; else run_as_root $*; fi ;; -bd|--ban-del ) if [[ "$EUID" -eq 0 ]]; then shift; ban_del $*; else run_as_root $*; fi ;; + -fp|--fix-permissions ) if [[ "$EUID" -eq 0 ]]; then shift; fix_permissions $*; else run_as_root $*; fi ;; + -as|--admin-sync ) if [[ "$EUID" -eq 0 ]]; then shift; admin_sync ; else run_as_root $*; fi ;; + -pg|--password-game ) if [[ "$EUID" -eq 0 ]]; then shift; Pass="$1"; shift ; password_game "$Pass" $*; else run_as_root $*; fi ;; + -pa|--password-admin ) if [[ "$EUID" -eq 0 ]]; then shift; Pass="$1"; shift ; password_admin "$Pass" $*; else run_as_root $*; fi ;; * ) echo "Command not recognized: $1"; exit 1 ;; esac diff --git a/SOURCES/kf2-srv-beta@.service b/SOURCES/kf2-srv-beta@.service index 7895fdd..18df560 100644 --- a/SOURCES/kf2-srv-beta@.service +++ b/SOURCES/kf2-srv-beta@.service @@ -8,7 +8,7 @@ Type=simple StandardOutput=null StandardError=null EnvironmentFile=/etc/kf2-srv/instances-beta/%i/main.conf -ExecStart=/usr/games/kf2-srv-beta/Binaries/Win64/KFGameSteamServer.bin.x86_64 $Args configsubdir=instances/%i $PortW $PortQ $PortG +ExecStart=/usr/games/kf2-srv-beta/Binaries/Win64/KFGameSteamServer.bin.x86_64 ${Map}?Difficulty=${Difficulty}?GameLength=${Length}?Game=${Game}${Args} configsubdir=instances/%i -webadminport=${PortWeb} -queryport=${PortQuery} -port=${PortGame} Restart=always NoNewPrivileges=yes diff --git a/SOURCES/kf2-srv.conf b/SOURCES/kf2-srv.conf old mode 100644 new mode 100755 index 2aa8d49..48935f0 --- a/SOURCES/kf2-srv.conf +++ b/SOURCES/kf2-srv.conf @@ -1 +1,19 @@ -#BranchName="preview" +# Displays game difficulty +# You can rename them as you like +DiffArray=('Normal' 'Hard' 'Suicide' 'Hell') + +# Displays the number of waves +# You can rename them as you like +WaveArray=('4' '7' '10') + +# Add custom gamemodes to the end of the list, similar to what is already there: +ModeArray['KFGameContent.KFGameInfo_Survival']='Survival' +ModeArray['KFGameContent.KFGameInfo_WeeklySurvival']='Weekly' +ModeArray['KFGameContent.KFGameInfo_Endless']='Endless' +ModeArray['KFGameContent.KFGameInfo_Objective']='Objective' +ModeArray['KFGameContent.KFGameInfo_VersusSurvival']='Versus' + +# Bot default password +# To change the password for the bot, you must do this here and in WebAdmin. +# Otherwise, the bot will stop working and some actions cannot be done on running servers +ServerBotPassword=VerySecretBotPassword diff --git a/SOURCES/kf2-srv@.service b/SOURCES/kf2-srv@.service index 4764fc3..923ebdd 100644 --- a/SOURCES/kf2-srv@.service +++ b/SOURCES/kf2-srv@.service @@ -8,7 +8,7 @@ Type=simple StandardOutput=null StandardError=null EnvironmentFile=/etc/kf2-srv/instances/%i/main.conf -ExecStart=/usr/games/kf2-srv/Binaries/Win64/KFGameSteamServer.bin.x86_64 $Args configsubdir=instances/%i $PortW $PortQ $PortG +ExecStart=/usr/games/kf2-srv/Binaries/Win64/KFGameSteamServer.bin.x86_64 ${Map}?Difficulty=${Difficulty}?GameLength=${Length}?Game=${Game}${Args} configsubdir=instances/%i -webadminport=${PortWeb} -queryport=${PortQuery} -port=${PortGame} Restart=always NoNewPrivileges=yes diff --git a/SOURCES/main.conf.template b/SOURCES/main.conf.template index fca621e..1dac045 100644 --- a/SOURCES/main.conf.template +++ b/SOURCES/main.conf.template @@ -1,29 +1,36 @@ LANG=en_US.UTF-8 -PortW=-webadminport=8080 -PortQ=-queryport=27015 -PortG=-port=7777 +PortWeb=8080 +PortQuery=27015 +PortGame=7777 + +# Default Map +Map=KF-Nuked -# First arg: map name -# # Difficulty: # Normal: 0 # Hard: 1 # Suicide: 2 # Hell: 3 -# +Difficulty=2 + # Game: # Survival: KFGameContent.KFGameInfo_Survival # WeeklyOutbreak: KFGameContent.KFGameInfo_WeeklySurvival # Endless: KFGameContent.KFGameInfo_Endless # Objective: KFGameContent.KFGameInfo_Objective # Versus: KFGameContent.KFGameInfo_VersusSurvival -# +Game=KFGameContent.KFGameInfo_Endless + # GameLength: # 4 waves: 0 # 7 waves: 1 # 10 waves: 2 -Args=kf-bioticslab?Difficulty=0?Game=KFGameContent.KFGameInfo_Survival?GameLength=2 +Length=2 + +# Additional parameters +# If the parameter is used, it must necessarily begin with a character '?' +Args= # Notes for yourself -Description="Default description" +Comment= diff --git a/SPECS/kf2-srv.spec b/SPECS/kf2-srv.spec index 53b5fed..616a3e5 100644 --- a/SPECS/kf2-srv.spec +++ b/SPECS/kf2-srv.spec @@ -1,7 +1,7 @@ %global steamuser steam Name: kf2-srv -Version: 0.8.0 +Version: 0.9.0 Release: 1%{dist} Summary: Killing Floor 2 server Group: Amusements/Games @@ -18,6 +18,7 @@ Source7: main.conf.template Source8: %{name}-beta@.service Source9: %{name}-beta-update.service Source10: %{name}-beta-update.timer +Source11: %{name}.conf Requires: systemd >= 219 Requires: steamcmd @@ -31,7 +32,7 @@ Requires: util-linux Requires: sudo Requires: psmisc Requires: gawk -Requires: multini >= 0.2 +Requires: multini >= 0.2.3 Provides: %{name} @@ -63,21 +64,23 @@ install -m 644 %{SOURCE7} %{buildroot}/%{_sysconfdir}/%{name} install -m 644 %{SOURCE8} %{buildroot}/%{_prefix}/lib/systemd/system install -m 644 %{SOURCE9} %{buildroot}/%{_prefix}/lib/systemd/system install -m 644 %{SOURCE10} %{buildroot}/%{_prefix}/lib/systemd/system +install -m 644 %{SOURCE11} %{buildroot}/%{_sysconfdir}/%{name} %clean rm -rf $RPM_BUILD_ROOT %files -%attr(775,root,%{steamuser}) %dir %{_prefix}/games/%{name} -%attr(775,root,%{steamuser}) %dir %{_prefix}/games/%{name}-beta -%attr(775,root,%{steamuser}) %dir %{_sysconfdir}/%{name} -%attr(775,root,%{steamuser}) %dir %{_sysconfdir}/%{name}/instances -%attr(775,root,%{steamuser}) %dir %{_sysconfdir}/%{name}/instances-beta -%attr(644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/main.conf.template -%attr(644,root,root) %config(noreplace) %{_prefix}/lib/firewalld/services/%{name}.xml -%attr(755,root,root) %{_bindir}/%{name} -%attr(755,root,root) %{_bindir}/%{name}-beta -%attr(644,root,root) %{_prefix}/lib/systemd/system/* +%attr(775,root,%{steamuser}) %dir %{_prefix}/games/%{name} +%attr(775,root,%{steamuser}) %dir %{_prefix}/games/%{name}-beta +%attr(775,root,%{steamuser}) %dir %{_sysconfdir}/%{name} +%attr(775,root,%{steamuser}) %dir %{_sysconfdir}/%{name}/instances +%attr(775,root,%{steamuser}) %dir %{_sysconfdir}/%{name}/instances-beta +%attr(644,root,%{steamuser}) %config(noreplace) %{_sysconfdir}/%{name}/main.conf.template +%attr(640,root,%{steamuser}) %config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf +%attr(644,root,root) %config(noreplace) %{_prefix}/lib/firewalld/services/%{name}.xml +%attr(755,root,root) %{_bindir}/%{name} +%attr(755,root,root) %{_bindir}/%{name}-beta +%attr(644,root,root) %{_prefix}/lib/systemd/system/* %preun if [[ $1 -eq 0 ]] ; then # Uninstall @@ -90,6 +93,14 @@ if [[ $1 -eq 0 ]] ; then # Uninstall fi %changelog +* Wed May 27 2020 GenZmeY - 0.9.0-1 +- new main.conf format; +- multiple WebAdmin and http auth by default; +- online actions; +- chat-bot; +- set password; +- refactoring. + * Mon Apr 27 2020 GenZmeY - 0.8.0-1 - use multini for ini edit; - add mutators support;