Jump to content
falcon911

SteamMod updater for a Windows Dedicated server

Recommended Posts

Just wanted to pass along some knowledge and maybe someone can fix the symlinks. But I found a old ARMA 3 script for a Windows dedicated server from  a user named tissue901

(original link: https://forums.bohemia.net/forums/topic/202897-dedicated-windows-server-updater-steam-workshop-and-game/)

While I got it to work with my server your mileage may vary. 

This is a  python script to automate updating my Windows Dedicated server. I've only tested it on Python 3.6 but I think it would work for any version. Just update the directories and files section to where your stuff is located.  The "WorkshopItems.txt" file just contains the workshop item number and a human readable string which automatically gets changed to a lowercase name without spaces.  It uses a symbolic link to add the mods to the server's addons folder instead of moving it so updating works without redownloading everything. 

Update.py

Spoiler

import os
import sys
from subprocess import Popen, PIPE, CalledProcessError, DEVNULL, STDOUT, check_call
import glob

DayzServerAppId = "223350"
DayzClientAppId = "221100"

modsDirectory = "D:\\DayzServer\\"
keysDirectory = "D:\\DayzServer\\keys\\"
DayzDirectory = "D:\\DayzServer\\"
steamCMD = "D:\\SteamCMD\\steamcmd.exe"
steamContentDirectory = "D:\\SteamCMD\\steamapps\\workshop\\content\\" + DayzClientAppId + "\\"
steamTempScript = "D:\\SteamCMD\\tempUpdateScript.txt"
steamAuth = "D:\\DayzServer\\Steamauth.txt"
workshopItems = "D:\\DayzServer\\Workshopitems.txt"

userLogin = "yoursteamid"
userPass = "Yourpassword"

def updateServer():
    print("Updating Server...")
    # Get the users login
    checkUserLogin()
    os.system(steamCMD + ' +login ' + userLogin + ' ' + userPass + ' +force_install_dir ' + DayzDirectory + ' "+app_update ' + DayzServerAppId + '" validate +quit')

def checkUserLogin():
    global userLogin
    global userPass
    
    if userLogin == "":
        userLogin = input("Steam> Username: ")
    if userPass == "":
        userPass = input("Steam> Password: ")
        
def copyKeys():
    for filename in glob.iglob(modsDirectory+'**\\*.bikey', recursive=True):
        os.system("xcopy " + filename + " " + keysDirectory + " /s /y")
        
error = ""

os.system('cls')

try:
    with open(steamAuth) as f:
        for line in f:
            info = line.split(" ")
            if len(info) == 2:
                userLogin = info[0]
                userPass = info[1]
except:
    pass

while True:
    userInput = input("Main Menu \n1. Update Server\n2. Update Mods\n4. Update Keys\n4. Exit\n" + error + ">> ")

    error = ""
    
    if userInput == "1":
        updateServer()
        input("Press any key to continue...")
        os.system('cls')
        
    elif userInput == "2":
        # Get the users login
        checkUserLogin()

        # Clear the temp script
        file = open(steamTempScript, 'w')

        script = "@ShutdownOnFailedCommand 1\n"
        script += "@NoPromptForPassword 1\n"
        script += "login " + userLogin + " " + userPass + "\n"
        script += "force_install_dir " + DayzDirectory + "\n"

        mods = {}

        # Loop through each item in the workshop file
        with open(workshopItems) as f:
            for line in f:
                modInfo = line.split(" ", 1)
                steamWorkshopId = modInfo[0].strip()
                modName = modInfo[1].strip()
                modFolder = "@"+modName.replace(" ", "_").lower()

                mods[steamWorkshopId] = {"name": modName, "folder": modFolder}
                
                script += 'workshop_download_item ' + DayzClientAppId + ' ' + steamWorkshopId + ' validate\n'

                # Make a link to the downloaded content (way better than moving...)
                symLink = modsDirectory + modFolder
                if not os.path.exists(symLink):
                   os.system('mklink /J ' + symLink + ' '"D:\\Dayzserver\\steamapps\\workshop\\content\\221100\\" + steamWorkshopId + '\n')

                   

        script += "quit"
         
        file.write(script)
        file.close()

        # Run the script
        print("\n=====================================\nLogging into Steam...\n=====================================")
        
        with Popen(steamCMD + " +runscript " + steamTempScript, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
            for line in p.stdout:
                line = line.strip()
                if line != "":
                    if line.find("Downloading item") != -1:
                        downloadingLine = line.split("Downloading item")
                        if downloadingLine[0]:  
                            print(downloadingLine[0])

                        try:
                            modIdLine = downloadingLine[1].strip().split(" ")
                            steamWorkshopId = modIdLine[0]
                            print("\n=====================================\nDownloading "+mods[steamWorkshopId]["name"] + " ["+str(steamWorkshopId)+"]...\n=====================================")
                        except:
                            pass
                            
                    else:
                        print(line)
        
        # Automatically copy bikeys over
        print("\n=====================================\nCopying addon keys...\n=====================================")
        copyKeys()
        
        input("\nPress any key to continue...")
        os.system('cls')
 
    elif userInput == "3":
        # Search for any bikeys and copy them into keys folder
        copyKeys()
        input("Press any key to continue...")
        os.system('cls')
    elif userInput == "4":
        sys.exit(0)
    elif userInput == "":
        os.system('cls')
    else:
        error = "[ERROR] Unknown choice. Try again\n"

 

WorkshopItems.txt

Spoiler

1630943713 Cl0ud_s_Military_Gear
1578593068 VanillaPlusPlus
1618400392 Better Combination Lock
1640091454 BleedTrail
1679548482 CityNames
1646187754 CodeLock
1633286229 DayZPlus_Guns
1571965849 DisableBaseDestruction
1608798126 DisableUnmountBarbedWire
1566911166 Mass_sManyItemOverhaul
1665663702 MoreGuns
1559212036 RPCFramework
1627811046 SpookArmbands
1590841260 Trader
1559317235 WeaponReduxPack
 

 

Note: If you happen to be good with Python scripting and you take a look at the original vs what I had to adjust above: You will notice that line (94 or 96 I believe) 

os.system('mklink /J ' + symLink + ' '"D:\\Dayzserver\\steamapps\\workshop\\content\\221100\\" + steamWorkshopId + '\n')

The symlink was not working from the original. I send a email to the dev. but have gotten no response as of yet. Maybe someone else could give it a go and correct it.  Either way match or adjust your folder structure accordingly. 

Edited by falcon911

Share this post


Link to post
Share on other sites

I use OmegaManager. A nice interface and automatically updates DayZ and all of the mods that I run on my server.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×