Page 1 of 2 12 LastLast
Results 1 to 20 of 38
  1. #1
    Community Member
    Join Date
    Jan 2010
    Posts
    1,396

    Default Launcher Script For Mac OS X 1.2.1

    This script can be run from the Terminal utility and allows you to enter the game directly on the toon you wish to play, bypassing the loading screen downloads, the launcher, and the character selection screen. You can alternatively go to the character selection screen first. You can multi-box by providing a toon name from a different account on the command line.

    Instructions for installing and running the script are embedded in the text.

    You can update to the latest script by backing up your old script, following the installation instructions for the new script, and then copying the "User modifiable section" from your old script into the new script. Alternatively, you can re-enter the user information manually.

    Note that the script is not able to patch the game when it has been updated. The real "Dungeons and Dragons Online" application must be run one time after every update to the game.

    If anyone runs into any trouble, please let me know.

    Code:
    #!/bin/bash
    
    #############################################################################
    # General Information
    #
    # Command Line Interface launcher for Dungeons & Dragons online.
    #
    # To use this script, follow the instructions in the sections:
    #     1) Create the script
    #     2) Personalize the script
    #     3) Play the game
    #
    # Note that this script cannot update the game. If it fails to work, run the
    # original DDO Launcher to allow it to perform any pending updates first.
    #
    # (C) 2007-2011 SNy <SNy@bmx-chemnitz.de>
    #
    # AtomicMew     6/3/12
    #   -modded to take command line args and windoze use
    #
    # Kaytis        5/31/13     v 1.1
    #   -modded to work on Mac OS X
    #
    # Kaytis        2/18/15     v 1.2
    #   -updated to match new login protocols
    #
    # Kaytis        11/30/15    v 1.2.1
    #   -disabled peer verification to bypass invalid certificates
    #
    # Kaytis        4/4/19      v 1.3
    #   -simplify instructions
    #
    
    #############################################################################
    # Create the script
    #
    #     1) Open TextEdit, create a new document, and paste all of this text into it.
    #     2) Select menu item "Format" > "Make Plain Text" (if you don't see this option, ignore this step).
    #     3) Save the file as DNDLauncher.sh in your Applications folder.
    #     4) Open /Applications/Utilities/Terminal and type:
    #            chmod 755 /Applications/DNDLauncher.sh
    #     5) Hit the return key to execute the command.
    
    #############################################################################
    # Personalize the script
    #
    #     1) Fill in the following, by replacing:
    #            account_username_here,
    #            account_password_here, and
    #            server_name_here
    #     2) When you are done typing the values, save the file. Don't share the
    #        file with anyone. Your password is in it.
    
    account=account_username_here           # Main account username. No spaces anywhere.
    pass=account_password_here              # Main account password. No spaces anywhere.
    selectedServer=server_name_here         # Main server (AKA game world) name e.g. Orien. Capitalize the first letter!
    
    #############################################################################
    # Play the game
    #
    #     1) Open /Applications/Utilities/Terminal
    #     2) To start from the character selection screen, type:
    #             /Applications/DNDLauncher.sh
    #        To start with a specific character, type:
    #             /Applications/DNDLauncher.sh character_name
    #     3) Hit the return key to execute the command. The game will start.
    #
    # Handy tip: the up arrow will restore the last command you typed in the Terminal.
    # Handy tip: you do not need to leave this file open after personalizing it.
    
    #############################################################################
    # Advanced instructions
    #
    # If you want to multibox, you can do so by adding specific character names from
    # alternate account(s) in the following sections. To play an alternate account:
    #     1) Open /Applications/Utilities/Terminal
    #     2) Type:
    #             /Applications/DNDLauncher.sh alt_account_character_name
    #     3) Hit the return key -a new copy of the game will start.
    #
    # Handy tip: you can have as many copies of the game open as you have alternate
    # accounts. You can add more character names by duplicating an "elif" block.
    
    if [ "${1}" == "alt_account_character_name" ] ; then
    
    account=alt_account_username_here       # Alt account username
    pass=alt_account_password_here          # Alt account password
    selectedSub=0                           # Alt account subscription. Delete this or use '0' if you only have one
    selectedServer=alt_server_name_here     # Alt server name e.g. Orien
    
    elif [ "${1}" == "alt_account_character_name" ] ; then
    
    account=alt_account_username_here       # Alt account username
    pass=alt_account_password_here          # Alt account password
    selectedSub=0                           # Alt account subscription. Delete this or use '0' if you only have one
    selectedServer=alt_server_name_here     # Alt server name e.g. Orien
    
    elif [ "${1}" == "alt_account_character_name" ] ; then
    
    account=alt_account_username_here       # Alt account username
    pass=alt_account_password_here          # Alt account password
    selectedSub=0                           # Alt account subscription. Delete this or use '0' if you only have one
    selectedServer=alt_server_name_here     # Alt server name e.g. Orien
    
    fi
    
    
    #############################################################################
    # Launcher script
    
    # Snag the character name, if any, and stash it in the "character" variable.
    character="${1}"
    
    echo "-----------------------------------------------------------------------"
    echo -e "Welcome to the CLI launcher for DDO for Mac OS X version 1.3"
    echo "-----------------------------------------------------------------------"
    
    exe() { echo "> $@" ; "$@" ; }
    
    # make this script be callable from elsewhere (desktop shortcuts etc)
    oldDir=`pwd`
    gameDir="/Applications/DNDLauncher.app/Contents/Resources/"
    
    # change directory to where the launcher resources reside
    cd "${gameDir}"
    
    # cleanup temp directory for configuration files downloaded from the official servers
    rm -rf .launcher
    mkdir .launcher
    
    echo "Reading game configuration..."
    
    # Official launcher config file. The launcher config file starts it all.
    # Get Game and DataCenter settings.
    configFile="TurbineLauncher.exe.config"
    
    if ! [ -r "${configFile}" ] ; then
        echo -e "\nError: ${configFile} cannot be read.\n"
        cd "${oldDir}"
        exit
    fi
    
    game=`grep -h "DataCenter.GameName" "${configFile}" | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    glsDataCenter_URL=`grep -h "Launcher.DataCenterService.GLS" "${configFile}" | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    
    echo "Game Name:                    ${game}"
    echo "Game Login Server:            ${glsDataCenter_URL}"
    echo "-----------------------------------------------------------------------"
    
    # get configuration info (xml-file containing auth, patch and game servers with their corresponding settings)
    # NOTE: while a normal HTTP GET to /GLS.DataCenterServer/Service.asmx/GetDatacenters?game=LOTROEU
    #       works fine for the european datacenter, it does not work for the US/AU/... LOTRO one
    #       instead, we need to send a SOAP request there, ending up with a SOAP answer (no whitespace whatsoever)
    #       now, to have at least some whitespace we can deal with, sed is used to insert a newline after each closing xml tag below
    
    echo "Querying Game Login Server..."
    
    #   wget \
    #       --no-check-certificate -q \
    #       --header 'Content-Type: text/xml; charset=utf-8' \
    #       --header 'SOAPAction: "http://www.turbine.com/SE/GLS/GetDatacenters"' \
    #       --post-data "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><GetDatacenters xmlns=\"http://www.turbine.com/SE/GLS\"><game>${game}</game></GetDatacenters></soap:Body></soap:Envelope>" \
    #       "${glsDataCenter_URL}" -O .launcher/GLSDataCenter.config
    
    curl --silent \
        --insecure \
        --header 'Content-Type: text/xml; charset=utf-8' \
        --header 'SOAPAction: "http://www.turbine.com/SE/GLS/GetDatacenters"' \
        --data   "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><GetDatacenters xmlns=\"http://www.turbine.com/SE/GLS\"><game>${game}</game></GetDatacenters></soap:Body></soap:Envelope>" \
        "${glsDataCenter_URL}" \
        --output .launcher/GLSDataCenter.config
    
    if ! [ -r .launcher/GLSDataCenter.config ] ; then
        echo -e "\nError: Could not fetch GLS data center configuration.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Format the response by adding new lines after the closing xml tags.
    sed -e "s#\(</[^>]*>\)#\1_make_newline_#g" -i "" .launcher/GLSDataCenter.config
    awk '{ gsub(/_make_newline_/,"\n",$0); print }' .launcher/GLSDataCenter.config >> .launcher/GLSDataCenter.config.tmp
    rm -f .launcher/GLSDataCenter.config
    mv .launcher/GLSDataCenter.config.tmp .launcher/GLSDataCenter.config
    
    # Grab only the first DataCenter.
    echo -e "<!--\n  NOTE\n  This file is NOT a valid XML file!\n-->" >> .launcher/GLSDataCenter.config."${game}"
    cat .launcher/GLSDataCenter.config | sed -n -e "/^.*<Datacenter><Name>${game}<\/Name>/,/<\/Datacenter>.*$/ p" >> .launcher/GLSDataCenter.config."${game}"
    
    # Extract global server URLs
    patchServer_ADR=`grep  -h "<PatchServer>"                    .launcher/GLSDataCenter.config.${game} | grep -v '<!--.*-->' | sed -e "s/^.*<PatchServer>//;s/<\/PatchServer>.*$//"`
    launcherCfg_URL=`grep  -h "<LauncherConfigurationServer>"    .launcher/GLSDataCenter.config.${game} | grep -v '<!--.*-->' | sed -e "s/^.*<LauncherConfigurationServer>//;s/<\/LauncherConfigurationServer>.*$//"`
    authServer_URL=`grep   -h "<AuthServer>"                     .launcher/GLSDataCenter.config.${game} | grep -v '<!--.*-->' | sed -e "s/^.*<AuthServer>//;s/<\/AuthServer>.*$//"`
    
    # Extract world specific server URLs
    serverChat_URL=`grep   -h -A 4 "<World>" .launcher/GLSDataCenter.config.${game} | grep -F -A 3 "${selectedServer}" | grep -h "<ChatServerUrl>"   | grep -v '<!--.*-->' | sed -e "s/^.*<ChatServerUrl>//;s/<\/ChatServerUrl>.*$//"`
    serverStatus_URL=`grep -h -A 4 "<World>" .launcher/GLSDataCenter.config.${game} | grep -F -A 3 "${selectedServer}" | grep -h "<StatusServerUrl>" | grep -v '<!--.*-->' | sed -e "s/^.*<StatusServerUrl>//;s/<\/StatusServerUrl>.*$//"`
    
    # Look up the server info in the configuration file
    # The chat server address is given directly, other stuff needs another file (cache_$REALMNAME.xml) from the server
    
    
    if [ -z "${launcherCfg_URL}" ] || [ -z "${authServer_URL}" ] ; then
        echo -e "\nError: Could not extract one or more server URLs from the Game Login Server response.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Extract list of game servers into an array
    worlds=`grep -h -A 4 "<World>" .launcher/GLSDataCenter.config.${game} | grep "<Name>" | grep -v '<!--.*-->' | sed -e "s/^.*<Name>//;s/<\/Name>.*$//"`
    IFS=$'\n'
    i=0
    for name in ${worlds} ; do
        serverNames[$i]=${name}
        i=$(($i + 1))
    done
    serverNames[$i]="end-of-list"
    unset IFS
    
    echo "Launch Configuration Server:  ${launcherCfg_URL}"
    echo "Patch Server:                 ${patchServer_ADR}"
    echo "Authorization Server:         ${authServer_URL}"
    if [[ "${serverNames[0]}" != "end-of-list" ]] ; then
        echo "Available Worlds:             ${serverNames[0]}"
        i=1
        while [[ "${serverNames[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${serverNames[$i]}"
            i=$(($i + 1))
        done
    else
        echo "Available Worlds:             None"
        cd "${oldDir}"
        exit
    fi
    echo "${selectedServer} Chat Server:            ${serverChat_URL}"
    echo "${selectedServer} Status Server:          ${serverStatus_URL}"
    echo "-----------------------------------------------------------------------"
    
    echo "Querying Launch Configuration Server..."
    
    #   wget --no-check-certificate \
    #       -q "${launcherCfg_URL}" \
    #       -O .launcher/launcher.config
    
    curl --silent \
        --insecure \
        "${launcherCfg_URL}" \
        --output .launcher/launcher.config
    
    if ! [ -r .launcher/launcher.config ] ; then
        echo -e "\nError: Could not fetch dynamic launcher configuration.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Extract game settings from launcher configuration.
    worldQueue_URL=`grep        -h "WorldQueue.LoginQueue.URL"          .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    worldQueue_ARGTMPL=`grep    -h "WorldQueue.TakeANumber.Parameters"  .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    glsTicketLifetime=`grep     -h "GameClient.Arg.glsticketlifetime"   .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    support_URL=`grep           -h "GameClient.Arg.supporturl"          .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    bug_URL=`grep               -h "GameClient.Arg.bugurl"              .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    supportService_URL=`grep    -h "GameClient.Arg.supportserviceurl"   .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    gameClient_FILE=`grep       -h "GameClient.OSX.Filename"            .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    gameClient_ARGTMPL=`grep    -h "GameClient.OSX.ArgTemplate"         .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    
    echo "World Queue Server:           ${worldQueue_URL}"
    echo "World Queue Args:             ${worldQueue_ARGTMPL}"
    echo "GLS Ticket Lifetime:          ${glsTicketLifetime}"
    echo "Support URL:                  ${support_URL}"
    echo "Bug URL:                      ${bug_URL}"
    echo "Support Service URL:          ${supportService_URL}"
    echo "Game Client File:             ${gameClient_FILE}"
    echo "Game Client Args:             ${gameClient_ARGTMPL}"
    echo "-----------------------------------------------------------------------"
    
    ########### CHOOSE LANGUAGE
    languages[0]=english
    selectedLanguage=0
    
    ########### PATCHING
    # Note: This script cannot patch the game. Use the Launcher to do that.
    
    ########### AUTHENTICATION
    
    function GLSAuth() {
    
        # "submit" the login form via POST, will download a file called "LoginAccount"
        # NOTE: the same thing as with the DataCenterServer applies here
        #  the lotroeugls server even has a service description and test form online
        #  well, at least they provide the SOAP request body as well...
    
        #    wget \
        #        --no-check-certificate -q \
        #        --header 'Content-Type: text/xml; charset=utf-8' \
        #        --header 'SOAPAction: "http://www.turbine.com/SE/GLS/LoginAccount"' \
        #        --post-data "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><LoginAccount xmlns=\"http://www.turbine.com/SE/GLS\"><username>${account}</username><password>${pass}</password><additionalInfo></additionalInfo></LoginAccount></soap:Body></soap:Envelope>" \
        #            "${authServer_URL}" -O .launcher/GLSAuthServer.config
    
        curl --silent \
            --insecure \
            --header 'Content-Type: text/xml; charset=utf-8' \
            --header 'SOAPAction: "http://www.turbine.com/SE/GLS/LoginAccount"' \
            --data "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><LoginAccount xmlns=\"http://www.turbine.com/SE/GLS\"><username>${account}</username><password>${pass}</password><additionalInfo></additionalInfo></LoginAccount></soap:Body></soap:Envelope>" \
            "${authServer_URL}" \
            --output .launcher/GLSAuthServer.config
    
        if ! [ -s .launcher/GLSAuthServer.config ] ; then
            echo -e "\nError: GLS auth server request failed. Wrong account/password?\n"
            echo -e "\nRetry (Y/n)? "
            read retry
            if [[ $retry == "y" || $retry == "Y" || $retry == "" ]] ; then
                GLSAuth
            else
                cd "${oldDir}"
                exit
            fi
        fi
    }
    
    echo "Requesting account details and authentication token from the Authorization Server..."
    
    GLSAuth
    
    # Check for multiple game subscriptions for the authenticated account.
    
    # Insert whitespace after </GameSubscription> tags here (to have linebreaks as separators for accounts)
    sed -e "s#\(</GameSubscription>\)#\1_make_newline_#g" -i "" .launcher/GLSAuthServer.config
    awk '{ gsub(/_make_newline_/,"\n",$0); print }' .launcher/GLSAuthServer.config >> .launcher/GLSAuthServer.config.tmp
    rm -f .launcher/GLSAuthServer.config
    mv .launcher/GLSAuthServer.config.tmp .launcher/GLSAuthServer.config
    
    # Extract each of the ids as well as descriptions for subscriptions to the current game.
    subNames=`grep -h "<Game>${game}<\/Game>" .launcher/GLSAuthServer.config | grep "<Name>"        | grep -v '<!--.*-->' | sed -e "s/^.*<Name>//;s/<\/Name>.*$//"`
    subDescs=`grep -h "<Game>${game}<\/Game>" .launcher/GLSAuthServer.config | grep "<Description>" | grep -v '<!--.*-->' | sed -e "s/^.*<Description>//;s/<\/Description>.*$//"`
    IFS=$'\n'
    i=0
    for sub in ${subNames} ; do
        subs[$i]="${sub}"
        i=$(($i + 1))
    done
    subs[$i]="end-of-list"
    i=0
    for desc in ${subDescs} ; do
        descs[$i]="${desc}"
        i=$(($i + 1))
    done
    descs[$i]="end-of-list"
    unset IFS
    
    # Check for at least one active subscription.
    if [[ $i == 0 ]] ; then
        echo -e "\nError: There appears to be no subscription for ${game}.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Extract the ticket from the GLS auth file, check for failure
    # NOTE: only the id (not the ticket) is subscription-specific
    glsTicket=`sed -n -e "s/^.*<Ticket>//;s/<\/Ticket>.*$// p" .launcher/GLSAuthServer.config`
    if [[ -z "${glsTicket}" ]] ; then
        echo -e "\nError: Could not extract authetication token from the Authorization Server response.\n"
        cd "${oldDir}"
        exit
    fi
    
    if [[ "${subs[0]}" != "end-of-list" ]] ; then
        echo "Subscription Names:           ${subs[0]}"
        i=1
        while [[ "${subs[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${subs[$i]}"
            i=$(($i + 1))
        done
    else
        echo "Subscription Names:           None"
        cd "${oldDir}"
        exit
    fi
    if [[ "${descs[0]}" != "end-of-list" ]] ; then
        echo "Subscription Descriptions:    ${descs[0]}"
        i=1
        while [[ "${descs[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${descs[$i]}"
            i=$(($i + 1))
        done
    else
        echo "Subscription Descriptions:    None"
        cd "${oldDir}"
        exit
    fi
    echo "Authentication Token:         ${glsTicket}"
    echo "-----------------------------------------------------------------------"
    
    # If there are multiple subscriptions to the current game available for the account,
    # and we haven't set the subscription choice, ask which one to use.
    if [[ "${selectedSub}" == "" ]] ; then
        if [[ $i > 1 && "${selectedSub}" == "" ]] ; then
            i=0
            echo "You have the following subscriptions for $game:"
            while [[ "${subs[$i]}" != "end-of-list" ]] ; do
                echo -e "    $i: ${subs[$i]}\t'${descs[$i]}'"
                i=$(($i + 1))
            done
            echo -n "Please select the one you wish to use (enter the number on the left): "
            read selectedSub
        else
            selectedSub=0
        fi
    fi
    
    echo "Requesting world information for ${selectedServer} from the Status Server..."
    
    # Download the status file and get the server adress and login queue adress to
    # establish the connection.
    # TODO: this file also contains current availability information, use it
    
    #   wget --no-check-certificate \
    #       -q "$serverStatus_URL" \
    #       -O .launcher/server.config
    
    curl --silent \
        --insecure \
        "$serverStatus_URL" \
        --output .launcher/server.config
    
    # Extract the list of loginServers and queue URLs (two at this time, it seems)
    loginServers=`grep -h "<loginservers>" .launcher/server.config | grep -v '<!--.*-->' | sed -e "s/^.*<loginservers>//;s/<\/loginservers>.*$//"`
    
    queueUrls=`grep -h "<queueurls>" .launcher/server.config | grep -v '<!--.*-->' | sed -e "s/^.*<queueurls>//;s/<\/queueurls>.*$//"`
    if [ -z "${loginServers}" ] || [ -z "${queueUrls}" ] ; then
        echo -e "\nError: Could not extract world information for ${selectedServer}.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Create array of servers
    IFS=";"
    i=0
    for adr in ${loginServers} ; do
        serverAddresses[$i]="${adr}"
        i=$(($i + 1))
    done
    serverAddresses[$i]="end-of-list"
    i=0
    for adr in ${queueUrls} ; do
        serverQueues[$i]="${adr}"
        i=$(($i + 1))
    done
    serverQueues[$i]="end-of-list"
    unset IFS
    
    # Create the world queue login request for the requested world.
    # The ticket can contain special characters and needs to be URL encoded before
    # POSTing it (same for queue_url). launcher.config included a parameter template
    # for the world queue request, used the same way as the client args below
    serverAddress="${serverAddresses[0]}"
    serverQueue="${serverQueues[0]}"
    
    rawurlencode() {
      local string="${1}"
      local strlen=${#string}
      local encoded=""
    
      for (( pos=0 ; pos<strlen ; pos++ )); do
         c=${string:$pos:1}
         case "$c" in
            [-_.~a-zA-Z0-9] ) o="${c}" ;;
            * )               printf -v o '%%%02x' "'$c"
         esac
         encoded+="${o}"
      done
      echo "${encoded}"
    }
    
    glsTicketURLencoded=$(rawurlencode "${glsTicket}")
    loginQueueURLencoded=$(rawurlencode "${serverQueue}")
    
    worldQueue_ARGS=`echo "${worldQueue_ARGTMPL}" | sed -e "s/[{]0[}]/${subs[$selectedSub]}/;s/[{]1[}]/${glsTicketURLencoded}/;s/[{]2[}]/${loginQueueURLencoded}/;s/\&amp\;/\&/g"`
    
    if [[ "${serverAddresses[0]}" != "end-of-list" ]] ; then
        echo "${selectedServer} Login Servers:          ${serverAddresses[0]}"
        i=1
        while [[ "${serverAddresses[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${serverAddresses[$i]}"
            i=$(($i + 1))
        done
    else
        echo "${selectedServer} Login Servers:          None"
        cd "${oldDir}"
        exit
    fi
    if [[ "${serverQueues[0]}" != "end-of-list" ]] ; then
        echo "${selectedServer} Login Servers:          ${serverQueues[0]}"
        i=1
        while [[ "${serverQueues[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${serverQueues[$i]}"
            i=$(($i + 1))
        done
    else
        echo "${selectedServer} Login Servers:          None"
        cd "${oldDir}"
        exit
    fi
    echo "Selecting queue:              ${serverQueue}"
    echo "Queue Arguments:              ${worldQueue_ARGS}"
    echo "-----------------------------------------------------------------------"
    
    ########### LOGIN QUEUE / CLIENT START
    function JoinQueue() {
    
        # Now get a queue number from the world login queue so that the client can enqueue and authenticate
        inQueue=1
        while [ "${inQueue}" == "1" ]; do
    
            # loop when necessary
    
            #   wget --no-check-certificate \
            #       -q --post-data="${worldQueue_ARGS}" \
            #       "${worldQueue_URL}" \
            #       -O .launcher/WorldQueue.config
    
            curl --silent \
                --insecure \
                --data "${worldQueue_ARGS}" \
                "${worldQueue_URL}" \
                --output .launcher/WorldQueue.config
            if ! [ -r .launcher/WorldQueue.config ] ; then
                echo -e "\nError: World login queue request failed.\n"
                cd "${oldDir}"
                exit
            fi
    
            # check the result, should be HRESULT 0x00000000, indicating success (Windows API madness)
            hresult=`grep -h "<HResult>" .launcher/WorldQueue.config | grep -v '<!--.*-->' | sed -e "s/^.*<HResult>//;s/<\/HResult>.*$//"`
            if [ "${hresult}" != "0x00000000" ] ; then
                echo -e "\nError: World login queue response indicates failure."
                cd "${oldDir}"
                exit
            else
                # lets see what position we are at
                queuePos=`grep -h "<QueueNumber>" .launcher/WorldQueue.config | grep -v '<!--.*-->' | sed -e "s/^.*<QueueNumber>//;s/<\/QueueNumber>.*$//"`
                queueSrvd=`grep -h "<NowServingNumber>" .launcher/WorldQueue.config | grep -v '<!--.*-->' | sed -e "s/^.*<NowServingNumber>//;s/<\/NowServingNumber>.*$//"`
                queueAhead=$(( ${queuePos} - ${queueSrvd} ))
                if [ ${queueAhead} -gt 0 ]; then
                    # d'oh, need to wait
                    echo -e "\n${queueAhead} ahead in queue, retrying in 5s..."
                    sleep 5
                else
                    # hah, ready to go
                    inQueue=0
                fi
            fi
        done
    }
    
    echo "Joining ${selectedServer} Login Server queue..."
    
    # new: world queue is unused on (some?) EU servers, just like with DDO, skip if no queue URL
    if [ -n "${serverQueue}" ] ; then
        JoinQueue
    else
        echo -e "\nWorld login queue seems to be disabled, skipping..."
    fi
    
    echo "Login to ${selectedServer} successful."
    
    # OK, so we have a template for the client arguments and we have the arguments
    # Note that for replacing the glsTicket, I use s### instead of s/// due to the ticket containing slashes
    # Hopefully, it doesn't contain any sharp characters :)
    
    gameClient_ARGS=`echo "${gameClient_ARGTMPL}" | sed -e "
        s/[{]SUBSCRIPTION[}]/${subs[$selectedSub]}/;
        s/[{]LOGIN[}]/${serverAddress}/;
        s#[{]GLS[}]#${glsTicket}#;
        s/[{]CHAT[}]/${serverChat_URL}/;
        s/[{]LANG[}]/${languages[$selectedLanguage]}/;
        s#[{]AUTHSERVERURL[}]#${authServer_URL}#;
        s/[{]GLSTICKETLIFETIME[}]/${glsTicketLifetime}/;
        s#[{]SUPPORTURL[}]#${support_URL}#;
        s#[{]BUGURL[}]#${bug_URL}#;
        s#[{]SUPPORTSERVICEURL[}]#${supportService_URL}#;
        "`
    
    echo "Launching client with command line:"
    if [ -n "${character}" ] ; then
        echo "./${gameClient_FILE}/Contents/MacOS/dndclient ${gameClient_ARGS} -u ${character} &>/dev/null &"
        ./${gameClient_FILE}/Contents/MacOS/dndclient ${gameClient_ARGS} -u "${character}" &>/dev/null &
    else
        echo "./${gameClient_FILE}/Contents/MacOS/dndclient ${gameClient_ARGS} &>/dev/null &"
        ./${gameClient_FILE}/Contents/MacOS/dndclient ${gameClient_ARGS} &>/dev/null &
    fi
    
    echo "-----------------------------------------------------------------------"
    echo "Done."
    echo "-----------------------------------------------------------------------"
    
    # Get back to where the caller was
    cd "${oldDir}"
    
    exit
    Last edited by Kaytis; 06-18-2019 at 01:37 PM. Reason: 1.3 simplify instructions

  2. #2
    Community Member onivedlav's Avatar
    Join Date
    Mar 2010
    Location
    Thelanis
    Posts
    127

    Default

    Kaytis is this version currently working?

    I am getting the following error:
    Error: Could not extract world information for thelanis.

    Thank you once again for for sharing this newer version of the script. I hope i can get it to work and enjoy it!

  3. #3
    Community Member
    Join Date
    Jan 2010
    Posts
    1,396

    Default

    Quote Originally Posted by onivedlav View Post
    Kaytis is this version currently working?

    I am getting the following error:
    Error: Could not extract world information for thelanis.

    Thank you once again for for sharing this newer version of the script. I hope i can get it to work and enjoy it!
    You need to capitalize the 'T' in Thelanis. Modify your script and you should be all set.
    Last edited by Kaytis; 07-23-2015 at 01:13 AM. Reason: Gave wrong advice. Saw the real problem later.

  4. #4
    Community Member onivedlav's Avatar
    Join Date
    Mar 2010
    Location
    Thelanis
    Posts
    127

    Talking

    Working perfectly! Many thanks sr.

  5. #5
    Community Member TheCanuck's Avatar
    Join Date
    Jul 2015
    Location
    Calgary, Canada
    Posts
    17

    Default

    I've just tried to use this launcher and while the script runs fine, Launches the client properly. I see the game loading screen and then it crashes.

    Does this version still work?

    Thanks!!!

  6. #6
    Community Member
    Join Date
    Jan 2010
    Posts
    1,396

    Default

    Quote Originally Posted by TheCanuck View Post
    I've just tried to use this launcher and while the script runs fine, Launches the client properly. I see the game loading screen and then it crashes.

    Does this version still work?

    Thanks!!!
    Yes it still works. The script does not know how to apply game updates and when an un-patched client tries to launch it will crash. So when a new update is released you will need to run the official launcher "/Applications/Dungeons And Dragons Online" just one time so that it can patch the game. After that you can use the script again until the next game update.

  7. #7
    Community Member
    Join Date
    Jan 2010
    Posts
    1,396

    Default

    Bumping for version 1.2.1. Fixes a problem with invalid certificates.
    Last edited by Kaytis; 11-30-2015 at 10:09 PM.

  8. #8
    Community Member
    Join Date
    Jun 2014
    Posts
    21

    Default

    I'm having the same problem as TheCanuck was, it seems. I get a loading screen without a loading bar, the loading bar appears for a moment, then the client crashes.

    But I'm trying to use this because my launcher seems to be broken (it seems to stop after checking dat files, but before moving on). If I'm missing a patch,* I can't get it through the launcher.

    *When was the last patch? Unless something has been added since 28.1, I should be up to date.


    From the report that appears when the client crashes:
    Code:
    Crashed Thread:        0  Dispatch queue: com.apple.main-thread
    
    Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
    Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
    I'm using OS X 10.10.3.


    (Also, it would be nice to be able to put the server as an argument when running it, so you can connect to any server with one copy of the file.)
    Last edited by Zweisteine; 12-06-2015 at 01:19 PM. Reason: Closing parentheses

  9. #9
    Community Member
    Join Date
    Jan 2010
    Posts
    1,396

    Default

    Quote Originally Posted by Zweisteine View Post
    I'm having the same problem as TheCanuck was, it seems. I get a loading screen without a loading bar, the loading bar appears for a moment, then the client crashes.

    But I'm trying to use this because my launcher seems to be broken (it seems to stop after checking dat files, but before moving on). If I'm missing a patch,* I can't get it through the launcher.

    *When was the last patch? Unless something has been added since 28.1, I should be up to date.


    From the report that appears when the client crashes:
    Code:
    Crashed Thread:        0  Dispatch queue: com.apple.main-thread
    
    Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
    Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
    I'm using OS X 10.10.3.


    (Also, it would be nice to be able to put the server as an argument when running it, so you can connect to any server with one copy of the file.)
    I would guess that the application or application data is corrupt. Update to 10.10.5 and see if that helps. If not, you should try reinstalling it.

    Interesting idea about parameterizing the server. It wouldn't be that difficult to do. I will give it some thought.

  10. #10
    Community Member
    Join Date
    Jun 2014
    Posts
    21

    Default

    Quote Originally Posted by Kaytis View Post
    I would guess that the application or application data is corrupt.
    Well, I tried renaming/moving and redownloading all of the dat files, and nothing changed.

    Looks like I'm stuck reinstalling. Oh well.

    EDIT: Aaaaand it didn't help. Reinstalled the game completely, and it still hangs when patching dat files.

    EDIT 2: Updating to 10.10.5 seems to have done the trick. After doing so, it stopped for only a moment at checking dat files, then prompted me to download an update. I did so, and the game works fine now. Gotta sleep though, so I won't be testing the script again today.
    Last edited by Zweisteine; 12-06-2015 at 11:52 PM.

  11. #11
    Community Member
    Join Date
    Jun 2013
    Posts
    59

    Default

    Awesome script, thank you so much! I was trying to find a way to dual box on macOS, this script is the answer

  12. #12
    Community Member PwnHammer40K's Avatar
    Join Date
    Nov 2010
    Posts
    460

    Thumbs up

    Thank you!

  13. #13
    Community Member
    Join Date
    Feb 2019
    Posts
    49

    Default

    Quote Originally Posted by Kaytis View Post
    This script can be run from the Terminal utility and allows you to enter the game directly on the toon you wish to play, bypassing the loading screen downloads, the launcher, and the character selection screen. You can alternatively go to the character selection screen first. You can multi-box by providing a toon name from a different account on the command line.

    Instructions for installing and running the script are embedded in the text.

    You can update to the latest script by backing up your old script, following the installation instructions for the new script, and then copying the "User modifiable section" from your old script into the new script. Alternatively, you can re-enter the user information manually.

    Note that the script is not able to patch the game when it has been updated. The real "Dungeons and Dragons Online" application must be run one time after every update to the game.

    If anyone runs into any trouble, please let me know.

    Code:
    #!/bin/bash
    
    #############################################################################
    # General Information
    #
    # Launch DDO client from CLI.
    #
    # (C) 2007-2011 SNy <SNy@bmx-chemnitz.de>
    #
    # AtomicMew     6/3/12
    #   -modded to take command line args and windoze use
    #
    # Kaytis        5/31/13     v 1.1
    #   -modded to work on Mac OS X
    #
    # Kaytis        2/18/15     v 1.2
    #   -updated to match U24 login protocols
    #
    # Kaytis        11/30/15    v 1.2.1
    #   -disabled peer verification to bypass invalid certificates
    #
    
    #############################################################################
    # How to install
    #
    # Open TextEdit, create a new document and paste the entire text of this
    # document in, then select Format/Make Plain Text.
    # Save the file to /Applications/DNDLauncherTemplate.sh
    # Open /Applications/Utilities/Terminal and type:
    #
    # cp /Applications/DNDLauncherTemplate.sh /Applications/DNDLauncher.sh
    # chmod 755 /Applications/DNDLauncher.sh
    #
    # Go back to TextEdit. Close DNDLauncherTemplate.sh and open /Applications/DNDLauncher.sh
    #
    # Once you have DNDLauncher.sh open follow the rest of the instructions.
    # You will need to change everything that starts with "putYour".
    # For every alt account you want to bring in, provide the account username
    # and password. Provide the subscription index if you have more than one
    # subscription for the account (this is usually not the case).
    # Specify the server you play on by name.
    #   Wayfinder
    #   Ghallanda
    #   Argonnessen
    #   Thelanis
    #   Sarlona
    #   Khyber
    #   Cannith
    #   Orien
    # Duplicate lines 73 through 80 to add another alt account.
    # After making the mods save your file and quit TextEdit.
    #
    # To play a specific toon:
    # Open /Applications/Utilities/Terminal and type:
    # /Applications/DNDLauncher.sh putYourAltAccountToonnameHere
    # Hit the return key, and you will be taken to a unique DND process running that toon.
    # Use command-H to hide the DND process (or window it with the Options menu etc), and
    # repeat these steps to multi-box another toon in another DND process on the same machine.
    #
    # To go to the character selection screen of your main account:
    # Open /Applications/Utilities/Terminal and type:
    # /Applications/DNDLauncher.sh
    #
    # Handy tip: the up arrow will restore the last command you typed in the Terminal
    # even if you quit it between sessions.
    # 
    # This file will end up with your account usernames and passwords in it.
    # DON'T SHARE YOUR CUSTOMIZED VERSION WITH OTHER PEOPLE.
    # SHARE ONLY THE DNDLauncherTemplate.sh FILE.
    
    #############################################################################
    # User modifiable section
    
    if [ "${1}" == "putYourAltAccountToonnameHere" ] ; then
                                            # Alt account support
    account=putYourAltAccountUsernameHere   # Alt account username
    pass=putYourAltAccountPasswordHere      # Alt account password
    selectedSub=0                           # Alt account subscription. Delete this or use '0' if you only have one
    selectedServer=putYourServerNameHere    # Alt server name e.g. Orien
    user="${1}"
    
    elif [ "${1}" == "putYourAltAccountToonnameHere" ] ; then
                                            # Alt account support
    account=putYourAltAccountUsernameHere   # Alt account username
    pass=putYourAltAccountPasswordHere      # Alt account password
    selectedSub=0                           # Alt account subscription. Delete this or use '0' if you only have one
    selectedServer=putYourServerNameHere    # Alt server name e.g. Orien
    user="${1}"
    
    else
                                            # Main account support
    account=putYourMainAccountUsernameHere  # Main account username
    pass=putYourMainAccountPasswordHere     # Main account password
    selectedServer=putYourServerNameHere    # Alt server name e.g. Orien
    user="${1}"
    fi
    
    #############################################################################
    # Launcher script
    
    echo "-----------------------------------------------------------------------"
    echo -e "Welcome to the CLI launcher for DDO for Mac OS X version 1.2.1"
    echo "-----------------------------------------------------------------------"
    
    exe() { echo "> $@" ; "$@" ; }
    
    # make this script be callable from elsewhere (desktop shortcuts etc)
    oldDir=`pwd`
    gameDir="/Applications/DNDLauncher.app/Contents/Resources/"
    
    # change directory to where the launcher resources reside
    cd "${gameDir}"
    
    # cleanup temp directory for configuration files downloaded from the official servers
    rm -rf .launcher
    mkdir .launcher
    
    echo "Reading game configuration..."
    
    # Official launcher config file. The launcher config file starts it all.
    # Get Game and DataCenter settings.
    configFile="TurbineLauncher.exe.config"
    
    if ! [ -r "${configFile}" ] ; then
        echo -e "\nError: ${configFile} cannot be read.\n"
        cd "${oldDir}"
        exit
    fi
    
    game=`grep -h "DataCenter.GameName" "${configFile}" | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    glsDataCenter_URL=`grep -h "Launcher.DataCenterService.GLS" "${configFile}" | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    
    echo "Game Name:                    ${game}"
    echo "Game Login Server:            ${glsDataCenter_URL}"
    echo "-----------------------------------------------------------------------"
    
    # get configuration info (xml-file containing auth, patch and game servers with their corresponding settings)
    # NOTE: while a normal HTTP GET to /GLS.DataCenterServer/Service.asmx/GetDatacenters?game=LOTROEU
    #       works fine for the european datacenter, it does not work for the US/AU/... LOTRO one
    #       instead, we need to send a SOAP request there, ending up with a SOAP answer (no whitespace whatsoever)
    #       now, to have at least some whitespace we can deal with, sed is used to insert a newline after each closing xml tag below
    
    echo "Querying Game Login Server..."
    
    #   wget \
    #       --no-check-certificate -q \
    #       --header 'Content-Type: text/xml; charset=utf-8' \
    #       --header 'SOAPAction: "http://www.turbine.com/SE/GLS/GetDatacenters"' \
    #       --post-data "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><GetDatacenters xmlns=\"http://www.turbine.com/SE/GLS\"><game>${game}</game></GetDatacenters></soap:Body></soap:Envelope>" \
    #       "${glsDataCenter_URL}" -O .launcher/GLSDataCenter.config
    
    curl --silent \
        --insecure \
        --header 'Content-Type: text/xml; charset=utf-8' \
        --header 'SOAPAction: "http://www.turbine.com/SE/GLS/GetDatacenters"' \
        --data   "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><GetDatacenters xmlns=\"http://www.turbine.com/SE/GLS\"><game>${game}</game></GetDatacenters></soap:Body></soap:Envelope>" \
        "${glsDataCenter_URL}" \
        --output .launcher/GLSDataCenter.config
    
    if ! [ -r .launcher/GLSDataCenter.config ] ; then
        echo -e "\nError: Could not fetch GLS data center configuration.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Format the response by adding new lines after the closing xml tags.
    sed -e "s#\(</[^>]*>\)#\1_make_newline_#g" -i "" .launcher/GLSDataCenter.config
    awk '{ gsub(/_make_newline_/,"\n",$0); print }' .launcher/GLSDataCenter.config >> .launcher/GLSDataCenter.config.tmp
    rm -f .launcher/GLSDataCenter.config
    mv .launcher/GLSDataCenter.config.tmp .launcher/GLSDataCenter.config
    
    # Grab only the first DataCenter.
    echo -e "<!--\n  NOTE\n  This file is NOT a valid XML file!\n-->" >> .launcher/GLSDataCenter.config."${game}"
    cat .launcher/GLSDataCenter.config | sed -n -e "/^.*<Datacenter><Name>${game}<\/Name>/,/<\/Datacenter>.*$/ p" >> .launcher/GLSDataCenter.config."${game}"
    
    # Extract global server URLs
    patchServer_ADR=`grep  -h "<PatchServer>"                    .launcher/GLSDataCenter.config.${game} | grep -v '<!--.*-->' | sed -e "s/^.*<PatchServer>//;s/<\/PatchServer>.*$//"`
    launcherCfg_URL=`grep  -h "<LauncherConfigurationServer>"    .launcher/GLSDataCenter.config.${game} | grep -v '<!--.*-->' | sed -e "s/^.*<LauncherConfigurationServer>//;s/<\/LauncherConfigurationServer>.*$//"`
    authServer_URL=`grep   -h "<AuthServer>"                     .launcher/GLSDataCenter.config.${game} | grep -v '<!--.*-->' | sed -e "s/^.*<AuthServer>//;s/<\/AuthServer>.*$//"`
    
    # Extract world specific server URLs
    serverChat_URL=`grep   -h -A 4 "<World>" .launcher/GLSDataCenter.config.${game} | grep -F -A 3 "${selectedServer}" | grep -h "<ChatServerUrl>"   | grep -v '<!--.*-->' | sed -e "s/^.*<ChatServerUrl>//;s/<\/ChatServerUrl>.*$//"`
    serverStatus_URL=`grep -h -A 4 "<World>" .launcher/GLSDataCenter.config.${game} | grep -F -A 3 "${selectedServer}" | grep -h "<StatusServerUrl>" | grep -v '<!--.*-->' | sed -e "s/^.*<StatusServerUrl>//;s/<\/StatusServerUrl>.*$//"`
    
    # Look up the server info in the configuration file
    # The chat server address is given directly, other stuff needs another file (cache_$REALMNAME.xml) from the server
    
    
    if [ -z "${launcherCfg_URL}" ] || [ -z "${authServer_URL}" ] ; then
        echo -e "\nError: Could not extract one or more server URLs from the Game Login Server response.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Extract list of game servers into an array
    worlds=`grep -h -A 4 "<World>" .launcher/GLSDataCenter.config.${game} | grep "<Name>" | grep -v '<!--.*-->' | sed -e "s/^.*<Name>//;s/<\/Name>.*$//"`
    IFS=$'\n'
    i=0
    for name in ${worlds} ; do
        serverNames[$i]=${name}
        i=$(($i + 1))
    done
    serverNames[$i]="end-of-list"
    unset IFS
    
    echo "Launch Configuration Server:  ${launcherCfg_URL}"
    echo "Patch Server:                 ${patchServer_ADR}"
    echo "Authorization Server:         ${authServer_URL}"
    if [[ "${serverNames[0]}" != "end-of-list" ]] ; then
        echo "Available Worlds:             ${serverNames[0]}"
        i=1
        while [[ "${serverNames[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${serverNames[$i]}"
            i=$(($i + 1))
        done
    else
        echo "Available Worlds:             None"
        cd "${oldDir}"
        exit
    fi
    echo "${selectedServer} Chat Server:            ${serverChat_URL}"
    echo "${selectedServer} Status Server:          ${serverStatus_URL}"
    echo "-----------------------------------------------------------------------"
    
    echo "Querying Launch Configuration Server..."
    
    #   wget --no-check-certificate \
    #       -q "${launcherCfg_URL}" \
    #       -O .launcher/launcher.config
    
    curl --silent \
        --insecure \
        "${launcherCfg_URL}" \
        --output .launcher/launcher.config
    
    if ! [ -r .launcher/launcher.config ] ; then
        echo -e "\nError: Could not fetch dynamic launcher configuration.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Extract game settings from launcher configuration.
    worldQueue_URL=`grep        -h "WorldQueue.LoginQueue.URL"          .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    worldQueue_ARGTMPL=`grep    -h "WorldQueue.TakeANumber.Parameters"  .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    glsTicketLifetime=`grep     -h "GameClient.Arg.glsticketlifetime"   .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    support_URL=`grep           -h "GameClient.Arg.supporturl"          .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    bug_URL=`grep               -h "GameClient.Arg.bugurl"              .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    supportService_URL=`grep    -h "GameClient.Arg.supportserviceurl"   .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    gameClient_FILE=`grep       -h "GameClient.OSX.Filename"            .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    gameClient_ARGTMPL=`grep    -h "GameClient.OSX.ArgTemplate"         .launcher/launcher.config | grep -v '<!--.*-->' | sed -e "s/^.*value=\"\([^\"]*\)\".*$/\1/"`
    
    echo "World Queue Server:           ${worldQueue_URL}"
    echo "World Queue Args:             ${worldQueue_ARGTMPL}"
    echo "GLS Ticket Lifetime:          ${glsTicketLifetime}"
    echo "Support URL:                  ${support_URL}"
    echo "Bug URL:                      ${bug_URL}"
    echo "Support Service URL:          ${supportService_URL}"
    echo "Game Client File:             ${gameClient_FILE}"
    echo "Game Client Args:             ${gameClient_ARGTMPL}"
    echo "-----------------------------------------------------------------------"
    
    ########### CHOOSE LANGUAGE
    languages[0]=english
    selectedLanguage=0
    
    ########### PATCHING
    # Note: This script cannot patch the game. Use the Launcher to do that.
    
    ########### AUTHENTICATION
    
    function GLSAuth() {
    
        # "submit" the login form via POST, will download a file called "LoginAccount"
        # NOTE: the same thing as with the DataCenterServer applies here
        #  the lotroeugls server even has a service description and test form online
        #  well, at least they provide the SOAP request body as well...
    
        #    wget \
        #        --no-check-certificate -q \
        #        --header 'Content-Type: text/xml; charset=utf-8' \
        #        --header 'SOAPAction: "http://www.turbine.com/SE/GLS/LoginAccount"' \
        #        --post-data "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><LoginAccount xmlns=\"http://www.turbine.com/SE/GLS\"><username>${account}</username><password>${pass}</password><additionalInfo></additionalInfo></LoginAccount></soap:Body></soap:Envelope>" \
        #            "${authServer_URL}" -O .launcher/GLSAuthServer.config
    
        curl --silent \
            --insecure \
            --header 'Content-Type: text/xml; charset=utf-8' \
            --header 'SOAPAction: "http://www.turbine.com/SE/GLS/LoginAccount"' \
            --data "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><LoginAccount xmlns=\"http://www.turbine.com/SE/GLS\"><username>${account}</username><password>${pass}</password><additionalInfo></additionalInfo></LoginAccount></soap:Body></soap:Envelope>" \
            "${authServer_URL}" \
            --output .launcher/GLSAuthServer.config
    
        if ! [ -s .launcher/GLSAuthServer.config ] ; then
            echo -e "\nError: GLS auth server request failed. Wrong account/password?\n"
            echo -e "\nRetry (Y/n)? "
            read retry
            if [[ $retry == "y" || $retry == "Y" || $retry == "" ]] ; then
                GLSAuth
            else
                cd "${oldDir}"
                exit
            fi
        fi
    }
    
    echo "Requesting account details and authentication token from the Authorization Server..."
    
    GLSAuth
    
    # Check for multiple game subscriptions for the authenticated account.
    
    # Insert whitespace after </GameSubscription> tags here (to have linebreaks as separators for accounts)
    sed -e "s#\(</GameSubscription>\)#\1_make_newline_#g" -i "" .launcher/GLSAuthServer.config
    awk '{ gsub(/_make_newline_/,"\n",$0); print }' .launcher/GLSAuthServer.config >> .launcher/GLSAuthServer.config.tmp
    rm -f .launcher/GLSAuthServer.config
    mv .launcher/GLSAuthServer.config.tmp .launcher/GLSAuthServer.config
    
    # Extract each of the ids as well as descriptions for subscriptions to the current game.
    subNames=`grep -h "<Game>${game}<\/Game>" .launcher/GLSAuthServer.config | grep "<Name>"        | grep -v '<!--.*-->' | sed -e "s/^.*<Name>//;s/<\/Name>.*$//"`
    subDescs=`grep -h "<Game>${game}<\/Game>" .launcher/GLSAuthServer.config | grep "<Description>" | grep -v '<!--.*-->' | sed -e "s/^.*<Description>//;s/<\/Description>.*$//"`
    IFS=$'\n'
    i=0
    for sub in ${subNames} ; do
        subs[$i]="${sub}"
        i=$(($i + 1))
    done
    subs[$i]="end-of-list"
    i=0
    for desc in ${subDescs} ; do
        descs[$i]="${desc}"
        i=$(($i + 1))
    done
    descs[$i]="end-of-list"
    unset IFS
    
    # Check for at least one active subscription.
    if [[ $i == 0 ]] ; then
        echo -e "\nError: There appears to be no subscription for ${game}.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Extract the ticket from the GLS auth file, check for failure
    # NOTE: only the id (not the ticket) is subscription-specific
    glsTicket=`sed -n -e "s/^.*<Ticket>//;s/<\/Ticket>.*$// p" .launcher/GLSAuthServer.config`
    if [[ -z "${glsTicket}" ]] ; then
        echo -e "\nError: Could not extract authetication token from the Authorization Server response.\n"
        cd "${oldDir}"
        exit
    fi
    
    if [[ "${subs[0]}" != "end-of-list" ]] ; then
        echo "Subscription Names:           ${subs[0]}"
        i=1
        while [[ "${subs[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${subs[$i]}"
            i=$(($i + 1))
        done
    else
        echo "Subscription Names:           None"
        cd "${oldDir}"
        exit
    fi
    if [[ "${descs[0]}" != "end-of-list" ]] ; then
        echo "Subscription Descriptions:    ${descs[0]}"
        i=1
        while [[ "${descs[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${descs[$i]}"
            i=$(($i + 1))
        done
    else
        echo "Subscription Descriptions:    None"
        cd "${oldDir}"
        exit
    fi
    echo "Authentication Token:         ${glsTicket}"
    echo "-----------------------------------------------------------------------"
    
    # If there are multiple subscriptions to the current game available for the account,
    # and we haven't set the subscription choice, ask which one to use.
    if [[ "${selectedSub}" == "" ]] ; then
        if [[ $i > 1 && "${selectedSub}" == "" ]] ; then
            i=0
            echo "You have the following subscriptions for $game:"
            while [[ "${subs[$i]}" != "end-of-list" ]] ; do
                echo -e "    $i: ${subs[$i]}\t'${descs[$i]}'"
                i=$(($i + 1))
            done
            echo -n "Please select the one you wish to use (enter the number on the left): "
            read selectedSub
        else
            selectedSub=0
        fi
    fi
    
    echo "Requesting world information for ${selectedServer} from the Status Server..."
    
    # Download the status file and get the server adress and login queue adress to
    # establish the connection.
    # TODO: this file also contains current availability information, use it
    
    #   wget --no-check-certificate \
    #       -q "$serverStatus_URL" \
    #       -O .launcher/server.config
    
    curl --silent \
        --insecure \
        "$serverStatus_URL" \
        --output .launcher/server.config
    
    # Extract the list of loginServers and queue URLs (two at this time, it seems)
    loginServers=`grep -h "<loginservers>" .launcher/server.config | grep -v '<!--.*-->' | sed -e "s/^.*<loginservers>//;s/<\/loginservers>.*$//"`
    
    queueUrls=`grep -h "<queueurls>" .launcher/server.config | grep -v '<!--.*-->' | sed -e "s/^.*<queueurls>//;s/<\/queueurls>.*$//"`
    if [ -z "${loginServers}" ] || [ -z "${queueUrls}" ] ; then
        echo -e "\nError: Could not extract world information for ${selectedServer}.\n"
        cd "${oldDir}"
        exit
    fi
    
    # Create array of servers
    IFS=";"
    i=0
    for adr in ${loginServers} ; do
        serverAddresses[$i]="${adr}"
        i=$(($i + 1))
    done
    serverAddresses[$i]="end-of-list"
    i=0
    for adr in ${queueUrls} ; do
        serverQueues[$i]="${adr}"
        i=$(($i + 1))
    done
    serverQueues[$i]="end-of-list"
    unset IFS
    
    # Create the world queue login request for the requested world.
    # The ticket can contain special characters and needs to be URL encoded before
    # POSTing it (same for queue_url). launcher.config included a parameter template
    # for the world queue request, used the same way as the client args below
    serverAddress="${serverAddresses[0]}"
    serverQueue="${serverQueues[0]}"
    
    rawurlencode() {
      local string="${1}"
      local strlen=${#string}
      local encoded=""
    
      for (( pos=0 ; pos<strlen ; pos++ )); do
         c=${string:$pos:1}
         case "$c" in
            [-_.~a-zA-Z0-9] ) o="${c}" ;;
            * )               printf -v o '%%%02x' "'$c"
         esac
         encoded+="${o}"
      done
      echo "${encoded}"
    }
    
    glsTicketURLencoded=$(rawurlencode "${glsTicket}")
    loginQueueURLencoded=$(rawurlencode "${serverQueue}")
    
    worldQueue_ARGS=`echo "${worldQueue_ARGTMPL}" | sed -e "s/[{]0[}]/${subs[$selectedSub]}/;s/[{]1[}]/${glsTicketURLencoded}/;s/[{]2[}]/${loginQueueURLencoded}/;s/\&amp\;/\&/g"`
    
    if [[ "${serverAddresses[0]}" != "end-of-list" ]] ; then
        echo "${selectedServer} Login Servers:          ${serverAddresses[0]}"
        i=1
        while [[ "${serverAddresses[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${serverAddresses[$i]}"
            i=$(($i + 1))
        done
    else
        echo "${selectedServer} Login Servers:          None"
        cd "${oldDir}"
        exit
    fi
    if [[ "${serverQueues[0]}" != "end-of-list" ]] ; then
        echo "${selectedServer} Login Servers:          ${serverQueues[0]}"
        i=1
        while [[ "${serverQueues[$i]}" != "end-of-list" ]] ; do
            echo -e "                              ${serverQueues[$i]}"
            i=$(($i + 1))
        done
    else
        echo "${selectedServer} Login Servers:          None"
        cd "${oldDir}"
        exit
    fi
    echo "Selecting queue:              ${serverQueue}"
    echo "Queue Arguments:              ${worldQueue_ARGS}"
    echo "-----------------------------------------------------------------------"
    
    ########### LOGIN QUEUE / CLIENT START
    function JoinQueue() {
    
        # Now get a queue number from the world login queue so that the client can enqueue and authenticate
        inQueue=1
        while [ "${inQueue}" == "1" ]; do
    
            # loop when necessary
    
            #   wget --no-check-certificate \
            #       -q --post-data="${worldQueue_ARGS}" \
            #       "${worldQueue_URL}" \
            #       -O .launcher/WorldQueue.config
    
            curl --silent \
                --insecure \
                --data "${worldQueue_ARGS}" \
                "${worldQueue_URL}" \
                --output .launcher/WorldQueue.config
            if ! [ -r .launcher/WorldQueue.config ] ; then
                echo -e "\nError: World login queue request failed.\n"
                cd "${oldDir}"
                exit
            fi
    
            # check the result, should be HRESULT 0x00000000, indicating success (Windows API madness)
            hresult=`grep -h "<HResult>" .launcher/WorldQueue.config | grep -v '<!--.*-->' | sed -e "s/^.*<HResult>//;s/<\/HResult>.*$//"`
            if [ "${hresult}" != "0x00000000" ] ; then
                echo -e "\nError: World login queue response indicates failure."
                cd "${oldDir}"
                exit
            else
                # lets see what position we are at
                queuePos=`grep -h "<QueueNumber>" .launcher/WorldQueue.config | grep -v '<!--.*-->' | sed -e "s/^.*<QueueNumber>//;s/<\/QueueNumber>.*$//"`
                queueSrvd=`grep -h "<NowServingNumber>" .launcher/WorldQueue.config | grep -v '<!--.*-->' | sed -e "s/^.*<NowServingNumber>//;s/<\/NowServingNumber>.*$//"`
                queueAhead=$(( ${queuePos} - ${queueSrvd} ))
                if [ ${queueAhead} -gt 0 ]; then
                    # d'oh, need to wait
                    echo -e "\n${queueAhead} ahead in queue, retrying in 5s..."
                    sleep 5
                else
                    # hah, ready to go
                    inQueue=0
                fi
            fi
        done
    }
    
    echo "Joining ${selectedServer} Login Server queue..."
    
    # new: world queue is unused on (some?) EU servers, just like with DDO, skip if no queue URL
    if [ -n "${serverQueue}" ] ; then
        JoinQueue
    else
        echo -e "\nWorld login queue seems to be disabled, skipping..."
    fi
    
    echo "Login to ${selectedServer} successful."
    
    # OK, so we have a template for the client arguments and we have the arguments
    # Note that for replacing the glsTicket, I use s### instead of s/// due to the ticket containing slashes
    # Hopefully, it doesn't contain any sharp characters :)
    
    gameClient_ARGS=`echo "${gameClient_ARGTMPL}" | sed -e "
        s/[{]SUBSCRIPTION[}]/${subs[$selectedSub]}/;
        s/[{]LOGIN[}]/${serverAddress}/;
        s#[{]GLS[}]#${glsTicket}#;
        s/[{]CHAT[}]/${serverChat_URL}/;
        s/[{]LANG[}]/${languages[$selectedLanguage]}/;
        s#[{]AUTHSERVERURL[}]#${authServer_URL}#;
        s/[{]GLSTICKETLIFETIME[}]/${glsTicketLifetime}/;
        s#[{]SUPPORTURL[}]#${support_URL}#;
        s#[{]BUGURL[}]#${bug_URL}#;
        s#[{]SUPPORTSERVICEURL[}]#${supportService_URL}#;
        "`
    
    echo "Launching client with command line:"
    if [ -n "${user}" ] ; then
        echo "./${gameClient_FILE}/Contents/MacOS/dndclient ${gameClient_ARGS} -u ${user} &>/dev/null &"
        ./${gameClient_FILE}/Contents/MacOS/dndclient ${gameClient_ARGS} -u "${user}" &>/dev/null &
    else
        echo "./${gameClient_FILE}/Contents/MacOS/dndclient ${gameClient_ARGS} &>/dev/null &"
        ./${gameClient_FILE}/Contents/MacOS/dndclient ${gameClient_ARGS} &>/dev/null &
    fi
    
    echo "-----------------------------------------------------------------------"
    echo "Done."
    echo "-----------------------------------------------------------------------"
    
    # Get back to where the caller was
    cd "${oldDir}"
    
    exit
    yeah, just doesn't work, but as all things DDO, i'm guessing there are finer points here that aren't fully explained. thanks.

  14. #14
    Community Member
    Join Date
    Jan 2010
    Posts
    1,396

    Default

    Quote Originally Posted by Daarsurra View Post
    yeah, just doesn't work, but as all things DDO, i'm guessing there are finer points here that aren't fully explained. thanks.
    Hi Daarsurra. I still use the script all the time. What specifically do you see happening? Note that the script is not able to update the game. Every time SSG does an update, you will need to run the actual launcher one time to patch the game.

  15. #15
    Community Member
    Join Date
    Jan 2010
    Posts
    1,396

    Default

    I have tried to make the script easier to set up. I moved the three most important lines to the top of the script and made the overall steps a bit easier to follow. Multiboxing support has been moved down out of the way where it will be less of a distraction.

    As always, if something isn't clear, let me know!

  16. #16
    Community Member
    Join Date
    Feb 2016
    Posts
    2

    Default

    Quote Originally Posted by Kaytis View Post
    I have tried to make the script easier to set up. I moved the three most important lines to the top of the script and made the overall steps a bit easier to follow. Multiboxing support has been moved down out of the way where it will be less of a distraction.

    As always, if something isn't clear, let me know!
    I've entered my username, password, and server the same as I enter in the client but I get the following error:

    -----------------------------------------------------------------------
    Welcome to the CLI launcher for DDO for Mac OS X version 1.3
    -----------------------------------------------------------------------
    Reading game configuration...
    Game Name: DDO
    Game Login Server: http://gls.ddo.com/GLS.DataCenterServer/Service.asmx
    -----------------------------------------------------------------------
    Querying Game Login Server...
    Launch Configuration Server: http://gls.ddo.com/launcher/ddo/dndl...ver.config.xml
    Patch Server: patch.ddo.com:5015
    Authorization Server: https://gls-auth.ddo.com/GLS.AuthServer/Service.asmx
    Available Worlds: Cannith
    Argonnessen
    Wayfinder
    Thelanis
    Sarlona
    Khyber
    Ghallanda
    Orien
    Argonnessen Chat Server: 198.252.160.40:2900
    Argonnessen Status Server: http://gls.ddo.com/GLS.DataCenterSer...=10.192.145.11
    -----------------------------------------------------------------------
    Querying Launch Configuration Server...
    World Queue Server: https://gls.ddo.com/GLS.AuthServer/LoginQueue.aspx
    World Queue Args: command=TakeANumber&amp;subscription={0}&amp;ticke t={1}&amp;ticket_type=GLS&amp;queue_url={2}
    GLS Ticket Lifetime: 21600
    Support URL: https://tss.turbine.com/TSSTrowser/trowser.aspx
    Bug URL: http://ddobugs.turbine.com?task=ticket
    Support Service URL: https://tss.turbine.com/TSSTrowser/SubmitTicket.asmx
    Game Client File: dndclient.app
    Game Client Args: -a {SUBSCRIPTION} -h {LOGIN} --glsticketdirect {GLS} --chatserver {CHAT} --rodat on --language {LANG} --gametype DDO --authserverurl {AUTHSERVERURL} --glsticketlifetime {GLSTICKETLIFETIME} --supporturl {SUPPORTURL} --bugurl {BUGURL} --supportserviceurl {SUPPORTSERVICEURL}
    -----------------------------------------------------------------------
    Requesting account details and authentication token from the Authorization Server...

    Error: There appears to be no subscription for DDO.

    Any suggestions?

    Thanks!

    Eric Sten

  17. #17
    Community Member
    Join Date
    Jan 2010
    Posts
    1,396

    Default

    Hi Eric. It looks like you have done everything right. Finding the subscription itself should be automatic unless you have more than one. Can you confirm this didn’t happen during the DNS outages around the 3rd/4th May?

  18. #18
    Community Member
    Join Date
    Jan 2015
    Location
    Europe
    Posts
    3

    Default

    Dear Kaytis,
    thank you for keeping this launcher alive. Actually it's the only way to play from mac (without installing windows) and I really like the "bash scripting art".
    After 42.4 release the launcher fails, am I the one experiencing this issue (I don't know, due to local problems) or is it common to other users?

    Last update had the following changes that does not seem to be a big deal but are launcher-related:
    The launcher will now dynamically update your position in line if you are in a login queue.
    The launcher will no longer bounce you between multiple login queues at random.
    New splash screens are now checked and downloaded, if needed, in parallel instead of one at a time. Hopefully this will reduce the time spent on this stage.

    However I get the following output before it fails:
    Code:
    Initializing display with title 'Dungeons and Dragons Online'...
    /build/dnd/dnd_live/src/engine/client/device/osx/Device_OSX.cpp, 284: called.
    Initializing the smartbox...
    Initializing the user interface...
    Client ready
    Client::Connect() async logon begun.
    Connection failed (0x00000004:0x00CD0B73) to server 0, addr 198.252.160.45:9004
    ./my_ddo_launch.sh: line 589:  1686 Segmentation fault: 11  ./${gameClient_FILE}/Contents/MacOS/dndclient ${gameClient_ARGS}
    Seems to me that " gameClient_ARGS" could have been changed
    Kind regards,
    Stefano

  19. #19
    Community Member
    Join Date
    Feb 2019
    Posts
    49

    Default

    Quote Originally Posted by Kaytis View Post
    Hi Daarsurra. I still use the script all the time. What specifically do you see happening? Note that the script is not able to update the game. Every time SSG does an update, you will need to run the actual launcher one time to patch the game.
    i whole-heartedly apologize for that sh*** response. i've forgotten i even explored this; i'll give it a try again.

    EDIT: seems to work now, but unfortunately crashes just like the normal launcher ;[
    Last edited by Daarsurra; 08-13-2019 at 04:22 PM.

  20. #20
    Community Member
    Join Date
    Feb 2019
    Posts
    49

    Default

    Quote Originally Posted by DeamonMaster View Post
    I've entered my username, password, and server the same as I enter in the client but I get the following error:

    -----------------------------------------------------------------------
    Welcome to the CLI launcher for DDO for Mac OS X version 1.3
    -----------------------------------------------------------------------
    Reading game configuration...
    Game Name: DDO
    Game Login Server: http://gls.ddo.com/GLS.DataCenterServer/Service.asmx
    -----------------------------------------------------------------------
    Querying Game Login Server...
    Launch Configuration Server: http://gls.ddo.com/launcher/ddo/dndl...ver.config.xml
    Patch Server: patch.ddo.com:5015
    Authorization Server: https://gls-auth.ddo.com/GLS.AuthServer/Service.asmx
    Available Worlds: Cannith
    Argonnessen
    Wayfinder
    Thelanis
    Sarlona
    Khyber
    Ghallanda
    Orien
    Argonnessen Chat Server: 198.252.160.40:2900
    Argonnessen Status Server: http://gls.ddo.com/GLS.DataCenterSer...=10.192.145.11
    -----------------------------------------------------------------------
    Querying Launch Configuration Server...
    World Queue Server: https://gls.ddo.com/GLS.AuthServer/LoginQueue.aspx
    World Queue Args: command=TakeANumber&amp;subscription={0}&amp;ticke t={1}&amp;ticket_type=GLS&amp;queue_url={2}
    GLS Ticket Lifetime: 21600
    Support URL: https://tss.turbine.com/TSSTrowser/trowser.aspx
    Bug URL: http://ddobugs.turbine.com?task=ticket
    Support Service URL: https://tss.turbine.com/TSSTrowser/SubmitTicket.asmx
    Game Client File: dndclient.app
    Game Client Args: -a {SUBSCRIPTION} -h {LOGIN} --glsticketdirect {GLS} --chatserver {CHAT} --rodat on --language {LANG} --gametype DDO --authserverurl {AUTHSERVERURL} --glsticketlifetime {GLSTICKETLIFETIME} --supporturl {SUPPORTURL} --bugurl {BUGURL} --supportserviceurl {SUPPORTSERVICEURL}
    -----------------------------------------------------------------------
    Requesting account details and authentication token from the Authorization Server...

    Error: There appears to be no subscription for DDO.

    Any suggestions?

    Thanks!

    Eric Sten
    i fixed that by making sure that i left the portion in bold:
    "account=account_username_here, pass=account_password_here, selectedServer=server_name_here"

    for me it was:

    account=Daarsurra
    pass=********
    selectedServer=Orien

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

This form's session has expired. You need to reload the page.

Reload