feat: command to change load order of mods (#27)
* progress * progress * feat: progress * progress * done, needs more testing, pr -> change all functions to require -n before specifying name -> v0.4 (reindex db) * testing done
This commit is contained in:
@@ -304,6 +304,19 @@ Import mods and database from an archive file (coming from h2mm).
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function display_order_help() {
|
||||||
|
cat << EOF
|
||||||
|
Usage: h2mm order [OPTIONS] [MOD_NAME|MOD_INDEX] <NEW_INDEX>
|
||||||
|
Change order of a mod by name or index.
|
||||||
|
Options:
|
||||||
|
-i <index> Index of the mod to order.
|
||||||
|
-n <index> New index of the mod.
|
||||||
|
Usage:
|
||||||
|
h2mm order -n "Example mod" 1
|
||||||
|
h2mm order -i 1 2
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
function display_modpack_list_help() {
|
function display_modpack_list_help() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
Usage: h2mm modpack-list
|
Usage: h2mm modpack-list
|
||||||
@@ -519,8 +532,8 @@ function mod_disable() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# disable each mod file by adding disabled_ to the start of the filename
|
# disable each mod file by adding disabled_ to the start of the filename
|
||||||
files=$(get_files_by_entry_from_db "$entry")
|
current_mod_files=$(get_files_by_entry_from_db "$entry")
|
||||||
for file in $files; do
|
for file in $current_mod_files; do
|
||||||
[[ ! -f "$MODS_DIR/$file" ]] && { log ERROR "Mod file $file does not exist."; exit 1; }
|
[[ ! -f "$MODS_DIR/$file" ]] && { log ERROR "Mod file $file does not exist."; exit 1; }
|
||||||
|
|
||||||
disabled_file="disabled_$file"
|
disabled_file="disabled_$file"
|
||||||
@@ -538,7 +551,7 @@ function mod_disable() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
# downgrade mods with greater version number
|
# downgrade mods with greater version number
|
||||||
downgrade_mods "$files"
|
downgrade_mods "$current_mod_files"
|
||||||
|
|
||||||
# update the database
|
# update the database
|
||||||
sed -i "/^$mod_index,/s/ENABLED/DISABLED/" "$DB_FILE"
|
sed -i "/^$mod_index,/s/ENABLED/DISABLED/" "$DB_FILE"
|
||||||
@@ -575,13 +588,13 @@ function mod_enable() {
|
|||||||
|
|
||||||
[[ "$status" == "ENABLED" ]] && { log ERROR "Mod $mod_name is already enabled."; exit 1; }
|
[[ "$status" == "ENABLED" ]] && { log ERROR "Mod $mod_name is already enabled."; exit 1; }
|
||||||
|
|
||||||
files=$(get_files_by_entry_from_db "$entry")
|
current_mod_files=$(get_files_by_entry_from_db "$entry")
|
||||||
|
|
||||||
# upgrade mods with lower version number
|
# upgrade mods with lower version number
|
||||||
upgrade_mods "$files"
|
upgrade_mods "$current_mod_files"
|
||||||
|
|
||||||
# enable each mod file by removing disabled_ from the start of the filename
|
# enable each mod file by removing disabled_ from the start of the filename
|
||||||
for file in $files; do
|
for file in $current_mod_files; do
|
||||||
enabled_file=$(remove_disabled_prefix "$file")
|
enabled_file=$(remove_disabled_prefix "$file")
|
||||||
|
|
||||||
# check if the files exists
|
# check if the files exists
|
||||||
@@ -836,9 +849,9 @@ function mod_uninstall() {
|
|||||||
get_mod_name_and_index
|
get_mod_name_and_index
|
||||||
|
|
||||||
# delete mod files
|
# delete mod files
|
||||||
files=$(get_files_by_entry_from_db "$entry")
|
current_mod_files=$(get_files_by_entry_from_db "$entry")
|
||||||
|
|
||||||
for file in $files; do
|
for file in $current_mod_files; do
|
||||||
[[ ! -f "$MODS_DIR/$file" ]] && { log ERROR "Mod file $file does not exist."; exit 1; }
|
[[ ! -f "$MODS_DIR/$file" ]] && { log ERROR "Mod file $file does not exist."; exit 1; }
|
||||||
|
|
||||||
log INFO "Removing ${ORANGE}\$MODS_DIR/$file${NC}."
|
log INFO "Removing ${ORANGE}\$MODS_DIR/$file${NC}."
|
||||||
@@ -848,7 +861,7 @@ function mod_uninstall() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
# downgrade mods with greater version number, only if the mod is enabled
|
# downgrade mods with greater version number, only if the mod is enabled
|
||||||
[[ "$status" == "ENABLED" ]] && downgrade_mods "$files"
|
[[ "$status" == "ENABLED" ]] && downgrade_mods "$current_mod_files"
|
||||||
|
|
||||||
# remove entry from database
|
# remove entry from database
|
||||||
sed -i "/^$mod_index,/d" "$DB_FILE"
|
sed -i "/^$mod_index,/d" "$DB_FILE"
|
||||||
@@ -985,6 +998,173 @@ function mod_import() {
|
|||||||
log INFO "Mods ${GREEN}successfully${NC} imported."
|
log INFO "Mods ${GREEN}successfully${NC} imported."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mod_order {
|
||||||
|
[[ "$1" == "--help" || "$1" == "-h" ]] && { display_order_help; exit 0; }
|
||||||
|
|
||||||
|
local mod_name=""
|
||||||
|
local mod_index=""
|
||||||
|
local new_index=""
|
||||||
|
|
||||||
|
# parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-i)
|
||||||
|
mod_index="$2"; shift 2
|
||||||
|
;;
|
||||||
|
-n)
|
||||||
|
mod_name="$2"; shift 2
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
display_order_help; exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
new_index="$1"; shift 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -z "$mod_name" && -z "$mod_index" ]] && { log ERROR "Mod name or index is required to change order."; exit 1; }
|
||||||
|
|
||||||
|
# find mod files
|
||||||
|
get_mod_name_and_index
|
||||||
|
|
||||||
|
# get the number of mods
|
||||||
|
mod_count=$(($(cat "$DB_FILE" | wc -l) - 1))
|
||||||
|
|
||||||
|
# check if the mod is already at the desired index and if new index is valid
|
||||||
|
[[ "$mod_index" == "$new_index" ]] && { log ERROR "Mod $mod_name is already at index $new_index."; exit 1; }
|
||||||
|
[[ $new_index -lt 1 ]] && { log ERROR "Index can not be less than 1."; exit 1; }
|
||||||
|
[[ $new_index -gt $mod_count ]] && { log ERROR "Index can not be more than mod count (${mod_count})."; exit 1; }
|
||||||
|
|
||||||
|
# assert ascending or descending order
|
||||||
|
ascending_order=true
|
||||||
|
[[ $mod_index -gt $new_index ]] && ascending_order=false
|
||||||
|
|
||||||
|
# get entries between the indexes
|
||||||
|
if [[ $ascending_order == true ]]; then
|
||||||
|
entries=$(awk -v mod_index="$mod_index" -v new_index="$new_index" -F, 'NR > 1 && $1 > mod_index && $1 <= new_index {print $0}' "$DB_FILE")
|
||||||
|
else
|
||||||
|
entries=$(awk -v mod_index="$mod_index" -v new_index="$new_index" -F, 'NR > 1 && $1 < mod_index && $1 >= new_index {print $0}' "$DB_FILE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# get files for the current mod
|
||||||
|
IFS= current_mod_files=$(get_files_by_entry_from_db "$entry"); unset IFS
|
||||||
|
|
||||||
|
# step 1 - count how many replaces need to be done in hash table
|
||||||
|
declare -A replace_count
|
||||||
|
for file in $current_mod_files; do
|
||||||
|
extension=$(get_extension "$file")
|
||||||
|
basename=$(get_basename "$file")
|
||||||
|
|
||||||
|
# if the file has no extension, add the basename to the hash table or increment the count
|
||||||
|
if [[ -z "$extension" ]]; then
|
||||||
|
replace_count["$basename"]=$(( ${replace_count["$basename"]:-0} + 1 ))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# step 2.1 - iterate over the basenames, find and store the files with the same basenames as the ones we want to upgrade/downgrade
|
||||||
|
declare -A files_to_replace
|
||||||
|
for basename in "${!replace_count[@]}"; do
|
||||||
|
IFS= files_to_replace["$basename"]=$(echo "$entries" | awk -F, '{print $4}' | grep -o "$basename\.patch_[^ ]*"); unset IFS
|
||||||
|
done
|
||||||
|
|
||||||
|
# step 2.2 - reverse sort the files_to_replace if we are in descending order
|
||||||
|
[[ $ascending_order == false ]] && for basename in "${!files_to_replace[@]}"; do
|
||||||
|
files_to_replace["$basename"]=$(echo "${files_to_replace["$basename"]}" | sort -rV)
|
||||||
|
done
|
||||||
|
|
||||||
|
# move current mod files to "t_$file" so we can move the new files to the correct index
|
||||||
|
for file in $current_mod_files; do
|
||||||
|
mv "$MODS_DIR/$file" "$MODS_DIR/t_$file"
|
||||||
|
[[ $? -ne 0 ]] && { log ERROR "Could not move mod file $file."; exit 1; }
|
||||||
|
done
|
||||||
|
|
||||||
|
# step 3 - for every basename in files_to_replace, add replace_count to each file's patch number and move
|
||||||
|
for basename in "${!files_to_replace[@]}"; do
|
||||||
|
files=$(echo "${files_to_replace["$basename"]}" | tr ' ' '\n')
|
||||||
|
|
||||||
|
for file in $files; do
|
||||||
|
basename=$(get_basename "$file")
|
||||||
|
patch_number=$(get_patch_number "$file")
|
||||||
|
extension=$(get_extension "$file")
|
||||||
|
|
||||||
|
# if ascending order, subtract replace_count to the patch number, otherwise add
|
||||||
|
operation="-"; [[ $ascending_order == false ]] && operation="+"
|
||||||
|
new_file="${basename}.patch_$(($patch_number $operation ${replace_count["$basename"]}))${extension}"
|
||||||
|
|
||||||
|
mv "$MODS_DIR/$file" "$MODS_DIR/$new_file"
|
||||||
|
[[ $? -ne 0 ]] && { log ERROR "Could not move mod file $file."; exit 1; }
|
||||||
|
|
||||||
|
log INFO "Reindexing ${ORANGE}$file${NC} to ${GREEN}$new_file${NC}."
|
||||||
|
|
||||||
|
# update db
|
||||||
|
sed -i "s/\(\b$file\b\)/$new_file/" "$DB_FILE"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# step 4 - for every file in current_mod_files, subtract the basename's array size of files_to_replace from the patch number
|
||||||
|
for file in $current_mod_files; do
|
||||||
|
basename=$(get_basename "$file")
|
||||||
|
patch_number=$(get_patch_number "$file")
|
||||||
|
extension=$(get_extension "$file")
|
||||||
|
|
||||||
|
# get size of only files without an extension
|
||||||
|
size=$(echo "${files_to_replace["$basename"]}" | grep -E "${basename}.patch_[0-9]+$" | tr ' ' '\n' | wc -l)
|
||||||
|
|
||||||
|
# in case size is 0, move t_file back to file later
|
||||||
|
new_file=${file}
|
||||||
|
|
||||||
|
if [[ $size -gt 0 ]]; then
|
||||||
|
# if ascending order, add size from the patch number, otherwise subtract
|
||||||
|
operation="+"; [[ $ascending_order == false ]] && operation="-"
|
||||||
|
new_file="${basename}.patch_$(($patch_number $operation $size))${extension}"
|
||||||
|
|
||||||
|
log INFO "Reindexing ${ORANGE}$file${NC} to ${GREEN}$new_file${NC}."
|
||||||
|
|
||||||
|
# dont forget current mod files are prefixed with t_
|
||||||
|
mv "$MODS_DIR/t_$file" "$MODS_DIR/t_$new_file"
|
||||||
|
[[ $? -ne 0 ]] && { log ERROR "Could not move mod file $file."; exit 1; }
|
||||||
|
|
||||||
|
# update file names
|
||||||
|
entry=$(echo "$entry" | sed "s/\(\b$file\b\)/$new_file/")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# move back temp file
|
||||||
|
mv "$MODS_DIR/t_$new_file" "$MODS_DIR/$new_file"
|
||||||
|
|
||||||
|
# update index (will be replaced in db later)
|
||||||
|
entry=$(echo "$entry" | sed "s/^$mod_index,/$new_index,/")
|
||||||
|
done
|
||||||
|
|
||||||
|
# step 5.1 - change current mod to t_index so we can move the other indexes
|
||||||
|
sed -i "s/^$mod_index,/t_$mod_index,/" "$DB_FILE"
|
||||||
|
|
||||||
|
# step 5.2 - reindex the rest of the mods
|
||||||
|
idxs=$(echo "$entries" | awk -F, '{print $1}' | tr ' ' '\n')
|
||||||
|
|
||||||
|
# step 5.3 - reverse sort the idxs if we are in descending order
|
||||||
|
[[ $ascending_order == false ]] && idxs=$(echo "$idxs" | sort -r)
|
||||||
|
|
||||||
|
for idx in $idxs; do
|
||||||
|
# if ascending order, subtract 1 from the index, otherwise add 1
|
||||||
|
operation="-"; [[ $ascending_order == false ]] && operation="+"
|
||||||
|
|
||||||
|
sed -i "s/^$idx,/$(($idx $operation 1)),/" "$DB_FILE"
|
||||||
|
done
|
||||||
|
|
||||||
|
# step 6 - move the entry to the new index
|
||||||
|
sed -i "/^t_$mod_index,/d" "$DB_FILE"
|
||||||
|
|
||||||
|
# weird edge case where the new index is the last index
|
||||||
|
if [[ $((new_index + 1)) -gt $(wc -l < "$DB_FILE") ]]; then
|
||||||
|
echo "$entry" >> "$DB_FILE"
|
||||||
|
else
|
||||||
|
sed -i "$((new_index + 1))i $entry" "$DB_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log INFO "Mod ${GREEN}successfully${NC} reindexed: $mod_name from $mod_index to $new_index."
|
||||||
|
}
|
||||||
|
|
||||||
# --- Modpacks management ---
|
# --- Modpacks management ---
|
||||||
|
|
||||||
function modpack_list() {
|
function modpack_list() {
|
||||||
@@ -1241,6 +1421,9 @@ function main() {
|
|||||||
"import"|"im")
|
"import"|"im")
|
||||||
mod_import "$@"
|
mod_import "$@"
|
||||||
;;
|
;;
|
||||||
|
"order"|"o")
|
||||||
|
mod_order "$@"
|
||||||
|
;;
|
||||||
"modpack-list"|"ml")
|
"modpack-list"|"ml")
|
||||||
modpack_list "$@"
|
modpack_list "$@"
|
||||||
;;
|
;;
|
||||||
|
|||||||
Reference in New Issue
Block a user