Changeset - a29cf0a83f46
[Not reviewed]
0 1 0
Branko Majic (branko) - 4 years ago 2020-07-04 22:16:24
branko@majic.rs
Noticket: Make Factorio Manager more robust by requesting all variables to be defined before use:

- Added missing server setting for port.
1 file changed with 50 insertions and 34 deletions:
0 comments (0 inline, 0 general) First comment
games/factorio_manager.sh
Show inline comments
 
@@ -15,12 +15,15 @@
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
#
 

	
 
# Treat unset variables as errors.
 
set -u
 

	
 
program="factorio_manager.sh"
 
version="0.1"
 

	
 
function synopsis() {
 
cat <<EOF
 
$program $version, helper tool for managing Factorio instances
 
@@ -257,13 +260,13 @@ function colorecho() {
 
        shift
 
    fi
 

	
 
    color="$1"
 
    text="$2"
 

	
 
    declare -A colors
 
    declare -A colors=()
 

	
 
    colors[black]="${_text_black}"
 
    colors[red]="${_text_red}"
 
    colors[green]="${_text_green}"
 
    colors[yellow]="${_text_yellow}"
 
    colors[blue]="${_text_blue}"
 
@@ -282,13 +285,13 @@ function colorprintf() {
 
    local reset="$_text_reset"
 

	
 
    local color="$1"
 
    local format="$2"
 
    shift 2
 

	
 
    declare -A colors
 
    declare -A colors=()
 

	
 
    colors[black]="${_text_black}"
 
    colors[red]="${_text_red}"
 
    colors[green]="${_text_green}"
 
    colors[yellow]="${_text_yellow}"
 
    colors[blue]="${_text_blue}"
 
@@ -325,20 +328,24 @@ function bold_blue() {
 
#
 
# The function will transform the answers to be fully usable in the
 
# server configuration file, making sure the parameters are properly
 
# escaped for use in a JSON file.
 
#
 
# Defaults are mostly identical to the ones listed under Factorio's
 
# default "server-setting.json" with some exceptions to options that
 
# default "server-settings.json" with some exceptions to options that
 
# may be considered invasion of privacy:
 
#
 
#   - User verification is disabled. Otherwise the central
 
#     authentication server will always be aware of who is playing the
 
#     game at the moment.
 
#   - Game is specifically configured to be non-public.
 
#
 
# In addition to settings from the "server-settings.json"
 
# configuiration file, settings also cover the server port (specified
 
# in the "config.ini").
 
#
 
# Arguments:
 
#
 
#   $1 (server_name)
 
#     Default name to use for the server.
 
#
 
# Sets:
 
@@ -352,22 +359,22 @@ function read_server_settings() {
 
    # Read arguments.
 
    local server_name="$1"
 

	
 
    # Local helper variables.
 
    local key="" value="" prompt="" confirmed="" item="" validation_passed possible_values i
 

	
 
    declare -A settings_prompt
 
    declare -A settings_description
 
    declare -A settings_type
 
    declare -A option
 
    declare -A settings_prompt=()
 
    declare -A settings_description=()
 
    declare -A settings_type=()
 
    declare -A option=()
 

	
 
    declare -a settings_order
 
    declare -a possible_options
 
    declare -a settings_order=()
 
    declare -a possible_options=()
 

	
 
    # Global variables set by the function.
 
    declare -g -A settings_value
 
    declare -g -A settings_value=()
 

	
 
    # Set-up listings of server settings. Each setting is described
 
    # with name, prompt, description, default value, and
 
    # type. Supported types are: bool, int, str, list (input treated
 
    # as space-delimited list).
 
    #
 
@@ -391,12 +398,21 @@ function read_server_settings() {
 
    settings_prompt["$key"]="Tags"
 
    settings_description["$key"]="Tags for the game that will appear in the listing (space-separated)"
 
    settings_value["$key"]=""
 
    settings_type["$key"]="list"
 
    settings_order+=("$key")
 

	
 
    # Not part of "server-settings.json", but important to show and
 
    # prompt the user for.
 
    key="port"
 
    settings_prompt["$key"]="Port"
 
    settings_description["$key"]="Port on which the server should listen"
 
    settings_value["$key"]="34197"
 
    settings_type["$key"]="int"
 
    settings_order+=("$key")
 

	
 
    key="max_players"
 
    settings_prompt["$key"]="Maximum players"
 
    settings_description["$key"]="Maximum number of players allowed, admins can join even a full server. 0 means unlimited."
 
    settings_value["$key"]="0"
 
    settings_type["$key"]="int"
 
    settings_order+=("$key")
 
@@ -700,13 +716,13 @@ quiet=0
 

	
 
# Set-up some default paths.
 
manager_directory="$HOME/.factorio"
 
game_installations_directory="$manager_directory/.game_installations"
 

	
 
# If no arguments were given, just show usage help.
 
if [[ -z $1 ]]; then
 
if [[ -z ${1-} ]]; then
 
    short_usage
 
    exit "$SUCCESS"
 
fi
 

	
 
# Parse the arguments
 
while getopts "qdvh" opt; do
 
@@ -736,13 +752,13 @@ shift
 
#==============#
 
# set-game-dir #
 
#==============#
 
if [[ $command == set-game-dir ]]; then
 

	
 
    # Read and verify additional positional arguments.
 
    game_installations_directory="$1"
 
    game_installations_directory="${1-}"
 
    shift
 

	
 
    if [[ -z $game_installations_directory ]]; then
 
        error "Missing argument: GAME_INSTALLATIONS_DIRECTORY"
 
        exit "$ERROR_ARGUMENTS"
 
    fi
 
@@ -838,13 +854,13 @@ elif [[ $command == create ]]; then
 
    if [[ ! -d $game_installations_directory ]]; then
 
        error "Game installations directory has not been properly set. Please run the set-game-dir command first."
 
        exit "$ERROR_CONFIGURATION"
 
    fi
 

	
 
    # Read positional arguments.
 
    instance="$1"
 
    instance="${1-}"
 
    shift
 

	
 
    # Calculate derived variables.
 
    instance_directory="$manager_directory/$instance"
 
    instance_config="$instance_directory/instance.conf"
 
    game_config="$instance_directory/config.ini"
 
@@ -930,13 +946,13 @@ EOF
 
    echo "Please read the warning above, and press any key to continue."
 
    read
 

	
 
elif [[ $command == launch ]]; then
 

	
 
    # Read positional arguments.
 
    instance="$1"
 
    instance="${1-}"
 
    shift
 

	
 
    # Set-up derived variables.
 
    instance_directory="$manager_directory/$instance"
 
    instance_config="$instance_directory/instance.conf"
 
    game_config="$instance_directory/config.ini"
 
@@ -997,14 +1013,14 @@ elif [[ $command == launch ]]; then
 
    else
 
        "$factorio_bin" --config "$game_config"
 
    fi
 

	
 
elif [[ $command == backup ]]; then
 
    # Read positional arguments.
 
    instance="$1"
 
    description="$2"
 
    instance="${1-}"
 
    description="${2-}"
 
    shift 2
 

	
 
    # Use timestamp-based names for backups.
 
    timestamp=$(date +%Y-%m-%d_%H:%M:%S)
 

	
 
    # Set-up derived variables.
 
@@ -1076,13 +1092,13 @@ elif [[ $command == backup ]]; then
 
#==============#
 
# list-backups #
 
#==============#
 
elif [[ $command == list-backups ]]; then
 

	
 
    # Read positional arguments.
 
    instance="$1"
 
    instance="${1-}"
 
    shift
 

	
 
    # Set-up derived variables.
 
    instance_directory="$manager_directory/$instance"
 
    instance_config="$instance_directory/instance.conf"
 
    game_config="$instance_directory/config.ini"
 
@@ -1151,14 +1167,14 @@ elif [[ $command == list-backups ]]; then
 
#=========#
 
# restore #
 
#=========#
 
elif [[ $command == restore ]]; then
 

	
 
    # Read positional arguments.
 
    instance="$1"
 
    backup_name="$2"
 
    instance="${1-}"
 
    backup_name="${2-}"
 
    shift 2
 

	
 
    # Set-up derived values.
 
    instance_directory="$manager_directory/$instance"
 
    restore_source="$instance_directory/.bak/$backup_name"
 
    backup_instance_config="$restore_source/instance.conf"
 
@@ -1280,14 +1296,14 @@ elif [[ $command == restore ]]; then
 
#===============#
 
# remove-backup #
 
#===============#
 
elif [[ $command == remove-backup ]]; then
 

	
 
    # Read positional arguments.
 
    instance="$1"
 
    backup_name="$2"
 
    instance="${1-}"
 
    backup_name="${2-}"
 
    shift 2
 

	
 
    # Verify positional arguments.
 
    if [[ -z $instance ]]; then
 
        error "Missing argument: INSTANCE"
 
        exit "$ERROR_ARGUMENTS"
 
@@ -1364,13 +1380,13 @@ elif [[ $command == remove-backup ]]; then
 

	
 
#=============#
 
# set-version #
 
#=============#
 
elif [[ $command == set-version ]]; then
 
    # Read positional arguments.
 
    instance="$1"
 
    instance="${1-}"
 
    shift
 

	
 
    # Verify positional arguments.
 
    if [[ -z $instance ]]; then
 
        error "Missing argument: INSTANCE"
 
        exit "$ERROR_ARGUMENTS"
 
@@ -1462,13 +1478,13 @@ elif [[ $command == info ]]; then
 
    if [[ ! -d $game_installations_directory ]]; then
 
        error "Game installations directory has not been properly set. Please run the set-game-dir command first."
 
        exit "$ERROR_CONFIGURATION"
 
    fi
 

	
 
    # Read positional arguments.
 
    instance="$1"
 
    instance="${1-}"
 
    shift
 

	
 
    # Verify positional arguments.
 
    if [[ -z $instance ]]; then
 
        error "Missing argument: INSTANCE"
 
        exit "$ERROR_ARGUMENTS"
 
@@ -1608,13 +1624,13 @@ elif [[ $command == info ]]; then
 
#========#
 
# remove #
 
#========#
 
elif [[ $command == remove ]]; then
 

	
 
    # Read positional arguments.
 
    instance="$1"
 
    instance="${1-}"
 
    shift
 

	
 
    # Verify positional arguments.
 
    if [[ -z $instance ]]; then
 
        error "Missing argument: INSTANCE"
 
        exit "$ERROR_ARGUMENTS"
 
@@ -1732,14 +1748,14 @@ elif [[ $command == copy ]]; then
 
    if [[ ! -d $game_installations_directory ]]; then
 
        error "Game installations directory has not been properly set. Please run the set-game-dir command first."
 
        exit "$ERROR_CONFIGURATION"
 
    fi
 

	
 
    # Read positional arguments.
 
    source_instance="$1"
 
    destination_instance="$2"
 
    source_instance="${1-}"
 
    destination_instance="${2-}"
 
    shift 2
 

	
 
    # Verify positional arguments.
 
    if [[ -z $source_instance ]]; then
 
        error "Missing argument: SOURCE_INSTANCE"
 
        exit "$ERROR_ARGUMENTS"
 
@@ -1782,13 +1798,13 @@ elif [[ $command == copy ]]; then
 

	
 
    (
 
        # Obtain lock - Factorio uses the same mechanism, so we should
 
        # be able to detect the game is running in this way.
 
        flock --exclusive --nonblock 200
 
        if [[ $? != 0 ]]; then
 
            error "Could not lock instance directory via lock file $lock_file. Is Factorio instance still running?"
 
            error "Could not lock instance directory via lock file $source_lock_file. Is Factorio instance still running?"
 
            exit "$ERROR_GENERAL"
 
        fi
 

	
 
        function remove_lock() {
 
            rm "$source_lock_file"
 
        }
 
@@ -1885,14 +1901,14 @@ elif [[ $command == import ]]; then
 
    if [[ ! -d $game_installations_directory ]]; then
 
        error "Game installations directory has not been properly set. Please run the set-game-dir command first."
 
        exit "$ERROR_CONFIGURATION"
 
    fi
 

	
 
    # Read positional arguments.
 
    instance="$1"
 
    source_directory="$2"
 
    instance="${1-}"
 
    source_directory="${2-}"
 
    shift 2
 

	
 
    # Verify positional arguments.
 
    if [[ -z $instance ]]; then
 
        error "Missing argument: INSTANCE"
 
        exit "$ERROR_ARGUMENTS"
 
@@ -1909,13 +1925,13 @@ elif [[ $command == import ]]; then
 
    game_config="$instance_directory/config.ini"
 

	
 
    source_config="$source_directory/config/config.ini"
 
    source_lock_file="$source_directory/.lock"
 

	
 
    # List of entries to import from the source directory.
 
    declare -A import_entries
 
    declare -A import_entries=()
 
    import_entries["achievements-modded.dat"]="contains achivement information for modded plays"
 
    import_entries["achievements.dat"]="contains achievement information for vanilla plays"
 
    import_entries["archive"]="contains desync reports"
 
    import_entries["blueprint-storage.dat"]="contains global (non-savegame specific) blueprints"
 
    import_entries["config/config.ini"]="contains game configuration, including things like shortcuts etc."
 
    import_entries["crop-cache.dat"]="purpose is not known"
 
@@ -1982,13 +1998,13 @@ elif [[ $command == import ]]; then
 
        # Sort the associative array keys.
 
        IFS=$'\n' import_entries_keys=($(sort <<<"${!import_entries[*]}"))
 
        unset IFS
 

	
 
        # Copy files and directories.
 
        echo
 
        declare -a missing_import_entries
 
        declare -a missing_import_entries=()
 
        for source_entry in "${import_entries_keys[@]}"; do
 
            source_entry_path="$source_directory/$source_entry"
 
            if [[ -e $source_entry_path ]]; then
 
                info "Importing $(bold_blue "$source_entry")..."
 

	
 
                if ! cp -a "$source_entry_path" "$instance_directory/"; then
 
@@ -2030,13 +2046,13 @@ EOF
 

	
 

	
 
#===============#
 
# create-server #
 
#===============#
 
elif [[ $command == create-server ]]; then
 
    instance="$1"
 
    instance="${1-}"
 

	
 
    # Make sure user has set directory with game installations - test
 
    # both symlink and target destination.
 
    if [[ ! -L $game_installations_directory ]]; then
 
        error "Game installations directory has not been properly set. Please run the set-game-dir command first."
 
        exit "$ERROR_CONFIGURATION"
 
@@ -2045,13 +2061,13 @@ elif [[ $command == create-server ]]; then
 
    if [[ ! -d $game_installations_directory ]]; then
 
        error "Game installations directory has not been properly set. Please run the set-game-dir command first."
 
        exit "$ERROR_CONFIGURATION"
 
    fi
 

	
 
    # Read positional arguments.
 
    instance="$1"
 
    instance="${1-}"
 
    shift
 

	
 
    # Calculate derived variables.
 
    instance_directory="$manager_directory/$instance"
 
    instance_config="$instance_directory/instance.conf"
 
    game_config="$instance_directory/config.ini"
 
@@ -2113,13 +2129,13 @@ write-data=${instance_directory}
 
[general]
 
locale=
 

	
 
[other]
 
check-updates=false
 
enable-crash-log-uploading=false
 
port=$server_port
 
port=${settings_value[port]}
 

	
 

	
 
[interface]
 

	
 
[controls]
 

	
0 comments (0 inline, 0 general) First comment
You need to be logged in to comment. Login now