From e3469b4d532f2f69cfd3710851af08d9545e5044 2021-02-10 21:22:57
From: Branko Majic <branko@majic.rs>
Date: 2021-02-10 21:22:57
Subject: [PATCH] Noticket: [factorio_manager.sh] Added commands for renaming and resetting the server map:

- Bumped the version as well.
- Added check for validating that a directory contains a server
  instance.
- Minor cleanup of an extra blank line and variable assignment.

---

diff --git a/games/factorio_manager.sh b/games/factorio_manager.sh
index 9b6393607c3a5fcd11ec9644e5fec6321947469f..2a904054b45b1b250fd61507bb5d0e841311a266 100755
--- a/games/factorio_manager.sh
+++ b/games/factorio_manager.sh
@@ -22,7 +22,7 @@
 set -u
 
 program="factorio_manager.sh"
-version="0.3.1"
+version="0.4.0"
 
 function synopsis() {
 cat <<EOF
@@ -35,10 +35,12 @@ Usage:
 
   $program [OPTIONS] create INSTANCE
   $program [OPTIONS] create-server INSTANCE
+  $program [OPTIONS] rename CURRENT_NAME NEW_NAME
   $program [OPTIONS] copy SOURCE_INSTANCE DESTINATION_INSTANCE
   $program [OPTIONS] remove INSTANCE
   $program [OPTIONS] import INSTANCE SOURCE_DIRECTORY
   $program [OPTIONS] set-version INSTANCE
+  $program [OPTIONS] reset-server-map INSTANCE
 
   $program [OPTIONS] versions
   $program [OPTIONS] install GAME_ARCHIVE
@@ -96,7 +98,6 @@ backup INSTANCE [DESCRIPTION]
     easier to distinguish between different backups. Hidden files
     (names starting with '.') will be omitted from the backup.
 
-
 copy SOURCE_INSTANCE DESTINATION_INSTANCE
 
     Creates a copy of an existing instance. Requires name of an
@@ -175,6 +176,12 @@ remove INSTANCE
     Removes the specified instance. User must confirm the action prior
     to any files being removed.
 
+rename CURRENT_NAME NEW_NAME
+
+    Renames an existing instnace. Requires current name of an
+    instance, as well as a new name. Command will refuse to rename the
+    instance if an instance with specified new name already exists.
+
 restore INSTANCE BACKUP_NAME
 
     Restores the specified instance from the specified backup. User
@@ -940,6 +947,9 @@ function read_server_settings() {
 #       game_archive
 #         Checks if file at designated path is a valid game archive.
 #
+#       server_instance_directory
+#         Checks if path contains a valid server instance.
+#
 #   $2 (path)
 #     Path that should be validated.
 #
@@ -1035,6 +1045,28 @@ function validate_path_or_terminate() {
             error "Supplied path does not point to a valid game archive."
             exit "$ERROR_ARGUMENTS"
         fi
+
+    elif [[ $path_test == "server_instance_directory" ]]; then
+        if [[ ! -d $path ]]; then
+            error "Missing instance directory: $path"
+            error "Perhaps you have misstyped the instance name or forgot to create one first?"
+            exit "$exit_code"
+        fi
+
+        if [[ ! -f $path/instance.conf ]]; then
+            error "Missing instance configuration file: $path/instance.conf"
+            exit "$exit_code"
+        fi
+
+        if [[ ! -f $path/config.ini ]]; then
+            error "Missing game configuration file: $path/config.ini"
+            exit "$exit_code"
+        fi
+
+        if [[ ! -f $path/server-settings.json ]]; then
+            error "Missing server settings file: $path/server-settings.json"
+            exit "$exit_code"
+        fi
     else
         error "Unable to validate path '$path', unsupported test requested: '$path_test'."
         exit "$ERROR_GENERAL"
@@ -2287,8 +2319,6 @@ elif [[ $command == create-server ]]; then
     # Make sure game installations directory has been set.
     validate_path_or_terminate "game_installations_directory" "$game_installations_directory" "$ERROR_CONFIGURATION"
 
-    instance="${1-}"
-
     # Read positional arguments.
     instance="${1-}"
     shift
@@ -2500,6 +2530,148 @@ elif [[ $command == install ]]; then
     fi
 
     success "Successfully installed game version: $(colorecho -n green "$game_version")"
+
+
+#==================#
+# reset-server-map #
+#==================#
+elif [[ $command == reset-server-map ]]; then
+
+    # Make sure game installations directory has been set.
+    validate_path_or_terminate "game_installations_directory" "$game_installations_directory" "$ERROR_CONFIGURATION"
+
+    # Read positional arguments.
+    instance="${1-}"
+    shift
+
+    # Calculate derived variables.
+    instance_directory="$manager_directory/$instance"
+    instance_config="$instance_directory/instance.conf"
+    game_config="$instance_directory/config.ini"
+    server_config="$instance_directory/server-settings.json"
+    main_save="$instance_directory/saves/default.zip"
+
+    # Verify arguments.
+    if [[ -z $instance ]]; then
+        error "Missing argument: INSTANCE"
+        exit "$ERROR_ARGUMENTS"
+    fi
+
+    # Validate that instance directory contains valid instance.
+    validate_path_or_terminate "server_instance_directory" "$instance_directory" "$ERROR_ARGUMENTS"
+
+    # Update instance write directory prior to launching - this is a
+    # failsafe in case it got changed by hand or perhaps the value
+    # comes from backups of a copied instance.
+    current_write_data=$(grep "^write-data=" "$game_config")
+    expected_write_data="write-data=${instance_directory}"
+
+    if [[ $current_write_data != "$expected_write_data" ]]; then
+        warning "Incorrect path specified for write-data in game configuration file: $game_config"
+        warning "Current configuration is: $current_write_data"
+        warning "Configuration will be replaced with: $expected_write_data"
+        sed -i -e "s#^write-data=.*#$expected_write_data#" "$game_config"
+    fi
+
+    # Read launcher configuration for the instance.
+    # shellcheck source=/dev/null
+    source "$instance_config"
+
+    if [[ -z $game_version ]]; then
+        error "Missing game version information in $game_config."
+        exit "$ERROR_CONFIGURATION"
+    fi
+
+    # Set-up paths for launching the game, and ensure they still exist
+    # (versions can be removed by user).
+    game_directory="${game_installations_directory}/${game_version}"
+    factorio_bin="$game_directory/bin/x64/factorio"
+
+    if [[ ! -e $factorio_bin ]]; then
+        error "Could not locate Factorio binary under: $factorio_bin"
+        error "Factorio $game_version installation may have been removed from game installations directory:"
+        error "   $(readlink -f "$game_installations_directory")"
+        exit "$ERROR_CONFIGURATION"
+    fi
+
+    # Request from user to confirm the destructive action.
+    critical_confirmation "Resetting the server map will wipe the default save game as well." \
+                          "Aborted server map reset, no changes have been made to instance files." \
+                          "$ERROR_GENERAL"
+
+    if ! rm -f "$main_save"; then
+        error "Could not remove the default save game."
+        exit "$ERROR_GENERAL"
+    fi
+
+    if ! "$factorio_bin" --config "$game_config" --create "$main_save"; then
+        error "Failed to generate default savegame/map under: $main_save"
+        exit "$ERROR_GENERAL"
+    fi
+
+
+#========#
+# rename #
+#========#
+elif [[ $command == rename ]]; then
+
+    # Make sure game installations directory has been set.
+    validate_path_or_terminate "game_installations_directory" "$game_installations_directory" "$ERROR_CONFIGURATION"
+
+    # Read positional arguments.
+    current_name="${1-}"
+    new_name="${2-}"
+    shift 2
+
+    # Verify positional arguments.
+    if [[ -z $current_name ]]; then
+        error "Missing argument: CURRENT_NAME"
+        exit "$ERROR_ARGUMENTS"
+    fi
+
+    if [[ -z $new_name ]]; then
+        error "Missing argument: NEW_NAME"
+        exit "$ERROR_ARGUMENTS"
+    fi
+
+    if [[ $current_name == "$new_name" ]]; then
+        error "New name must differ from current name."
+
+        exit "$ERROR_ARGUMENTS"
+    fi
+
+    # Calculate derived variables.
+    current_instance_directory="$manager_directory/$current_name"
+    current_instance_config="$current_instance_directory/instance.conf"
+    current_instance_lock_file="$current_instance_directory/.lock"
+    new_instance_directory="$manager_directory/$new_name"
+
+    # Validate that source instance directory contains valid instance.
+    validate_path_or_terminate "instance_directory" "$current_instance_directory" "$ERROR_ARGUMENTS"
+
+    # Make sure destination instance directory can be used.
+    validate_path_or_terminate "instance_directory_new" "$new_instance_directory" "$ERROR_ARGUMENTS"
+
+    (
+        # shellcheck disable=SC2094 # Lock file is not being read from.
+        lock "$current_instance_lock_file" 200
+
+        # Load source instance configuration.
+        # shellcheck source=/dev/null
+        source "$current_instance_config"
+
+        # Rename the instance.
+        mv "$current_instance_directory" "$new_instance_directory"
+
+        # Update write-data directory of destination instance,
+        # including the backups.
+        write_data="write-data=${new_instance_directory}"
+        find "$new_instance_directory/" -type f -name config.ini -exec \
+             sed -i -e "s#^write-data=.*#$write_data#" '{}' \;
+
+        success "Renamed instance $(colorecho -n green "$current_name") to $(colorecho -n green "$new_name")."
+
+    ) 200>"$current_instance_lock_file"
 else
     error "Invalid command: $command"