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
|
||||
}
|
||||
|
||||
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() {
|
||||
cat << EOF
|
||||
Usage: h2mm modpack-list
|
||||
@@ -519,8 +532,8 @@ function mod_disable() {
|
||||
fi
|
||||
|
||||
# disable each mod file by adding disabled_ to the start of the filename
|
||||
files=$(get_files_by_entry_from_db "$entry")
|
||||
for file in $files; do
|
||||
current_mod_files=$(get_files_by_entry_from_db "$entry")
|
||||
for file in $current_mod_files; do
|
||||
[[ ! -f "$MODS_DIR/$file" ]] && { log ERROR "Mod file $file does not exist."; exit 1; }
|
||||
|
||||
disabled_file="disabled_$file"
|
||||
@@ -538,7 +551,7 @@ function mod_disable() {
|
||||
done
|
||||
|
||||
# downgrade mods with greater version number
|
||||
downgrade_mods "$files"
|
||||
downgrade_mods "$current_mod_files"
|
||||
|
||||
# update the database
|
||||
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; }
|
||||
|
||||
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 "$files"
|
||||
upgrade_mods "$current_mod_files"
|
||||
|
||||
# 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")
|
||||
|
||||
# check if the files exists
|
||||
@@ -836,9 +849,9 @@ function mod_uninstall() {
|
||||
get_mod_name_and_index
|
||||
|
||||
# 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; }
|
||||
|
||||
log INFO "Removing ${ORANGE}\$MODS_DIR/$file${NC}."
|
||||
@@ -848,7 +861,7 @@ function mod_uninstall() {
|
||||
done
|
||||
|
||||
# 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
|
||||
sed -i "/^$mod_index,/d" "$DB_FILE"
|
||||
@@ -985,6 +998,173 @@ function mod_import() {
|
||||
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 ---
|
||||
|
||||
function modpack_list() {
|
||||
@@ -1241,6 +1421,9 @@ function main() {
|
||||
"import"|"im")
|
||||
mod_import "$@"
|
||||
;;
|
||||
"order"|"o")
|
||||
mod_order "$@"
|
||||
;;
|
||||
"modpack-list"|"ml")
|
||||
modpack_list "$@"
|
||||
;;
|
||||
|
||||
Reference in New Issue
Block a user