#!/bin/bash set -euo pipefail REPO_DIR="/tmp/mod_repo" SERVER_MODS_FILE="/tmp/server_mods.txt" MINECRAFT_MODS_DIR="/home/minecraft/mods" TACCZ_DIR="/home/minecraft/tacz" STATE_DIR="$REPO_DIR/state" MODPACK_DIR="$REPO_DIR/modpack" VERSION_FILE="$REPO_DIR/VERSION" GIT_REPO="ssh://git@jianfgit.xyz:220/jianf/servermods.git" MODRINTH_INDEX="$MODPACK_DIR/modrinth.index.json" TRUEMODS_DIR="$REPO_DIR/truemods" TRUEGUNPACKS_DIR="$REPO_DIR/truegunpacks" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" } get_current_version() { if [[ -f "$VERSION_FILE" ]]; then cat "$VERSION_FILE" else echo "0.0.0" fi } increment_version() { local version="$1" IFS='.' read -r major minor patch <<< "$version" patch=$((patch + 1)) echo "$major.$minor.$patch" } get_file_hash() { local file_path="$1" if [[ -f "$file_path" ]]; then sha1sum "$file_path" | awk '{print $1}' else echo "0000000000000000000000000000000000000000" fi } find_mod_file() { local base_name="$1" local mod_file mod_file=$(find "$MINECRAFT_MODS_DIR" -name "${base_name}-*.jar" | head -1 || echo "") if [[ -z "$mod_file" ]]; then mod_file="$MINECRAFT_MODS_DIR/${base_name}.jar" if [[ ! -f "$mod_file" ]]; then echo "" else echo "$mod_file" fi else echo "$mod_file" fi } find_gunpack_file() { local base_name="$1" local gunpack_file gunpack_file=$(find "$TACCZ_DIR" -name "${base_name}*" | head -1 || echo "") if [[ -z "$gunpack_file" ]]; then gunpack_file="$TACCZ_DIR/${base_name}" if [[ ! -f "$gunpack_file" ]]; then echo "" else echo "$gunpack_file" fi else echo "$gunpack_file" fi } create_modrinth_index() { local version="$1" local mods_json="$2" local gunpacks_json="$3" { echo '{' echo ' "formatVersion": 1,' echo ' "game": {' echo ' "type": "forge",' echo ' "version": "1.20.1"' echo ' },' echo " \"versionId\": \"$version\"," echo ' "name": "minimal-client-modpack",' echo ' "summary": "Minimal client modpack for connecting to the server",' echo ' "files": [' } > "$MODRINTH_INDEX" local first=true while IFS= read -r mod; do if [[ -n "$mod" ]]; then local mod_path mod_path=$(find_mod_file "$mod") if [[ -n "$mod_path" && -f "$mod_path" ]]; then local mod_filename mod_filename=$(basename "$mod_path") local hash hash=$(get_file_hash "$mod_path") if [[ "$first" == true ]]; then first=false else echo ',' >> "$MODRINTH_INDEX" fi { echo ' {' echo ' "path": "mods/'"$mod_filename"'",' echo ' "hashes": {' echo " \"sha1\": \"$hash\"" echo ' },' echo ' "env": {' echo ' "client": ["required"],' echo ' "server": ["unsupported"]' echo ' },' echo ' "downloads": []' echo ' }' } >> "$MODRINTH_INDEX" fi fi done < "$mods_json" while IFS= read -r gunpack; do if [[ -n "$gunpack" ]]; then gunpack=$(echo "$gunpack" | sed 's/^"//' | sed 's/"$//') local gunpack_path gunpack_path=$(find_gunpack_file "$gunpack") if [[ -n "$gunpack_path" && -f "$gunpack_path" ]]; then local gunpack_filename gunpack_filename=$(basename "$gunpack_path") local hash hash=$(get_file_hash "$gunpack_path") echo ',' >> "$MODRINTH_INDEX" { echo ' {' echo ' "path": "tacz/'"$gunpack_filename"'",' echo ' "hashes": {' echo " \"sha1\": \"$hash\"" echo ' },' echo ' "env": {' echo ' "client": ["required"],' echo ' "server": ["unsupported"]' echo ' },' echo ' "downloads": []' echo ' }' } >> "$MODRINTH_INDEX" fi fi done < "$gunpacks_json" { echo ' ]' echo '}' } >> "$MODRINTH_INDEX" } sync_mods() { mkdir -p "$TRUEMODS_DIR" while IFS= read -r mod; do if [[ -n "$mod" ]]; then local mod_path mod_path=$(find_mod_file "$mod") if [[ -n "$mod_path" && -f "$mod_path" ]]; then cp "$mod_path" "$TRUEMODS_DIR/" log "Copied $mod_path to $TRUEMODS_DIR/" fi fi done < "$1" } sync_gunpacks() { mkdir -p "$TRUEGUNPACKS_DIR" while IFS= read -r gunpack; do if [[ -n "$gunpack" ]]; then gunpack=$(echo "$gunpack" | sed 's/^"//' | sed 's/"$//') local gunpack_path gunpack_path=$(find_gunpack_file "$gunpack") if [[ -n "$gunpack_path" && -f "$gunpack_path" ]]; then cp "$gunpack_path" "$TRUEGUNPACKS_DIR/" log "Copied $gunpack_path to $TRUEGUNPACKS_DIR/" fi fi done < "$1" } main() { log "Starting modpack synchronization" mkdir -p "$STATE_DIR" mkdir -p "$MODPACK_DIR" mkdir -p "$REPO_DIR/tacz" mkdir -p "$TRUEMODS_DIR" mkdir -p "$TRUEGUNPACKS_DIR" if [[ ! -f "$SERVER_MODS_FILE" ]]; then log "ERROR: Server mods file not found: $SERVER_MODS_FILE" exit 1 fi if [[ ! -d "$MINECRAFT_MODS_DIR" ]]; then log "ERROR: Minecraft mods directory not found: $MINECRAFT_MODS_DIR" exit 1 fi if [[ ! -d "$TACCZ_DIR" ]]; then log "ERROR: TACCZ directory not found: $TACCZ_DIR" exit 1 fi grep -v "^disabled$" "$SERVER_MODS_FILE" | sed 's/-[0-9].*$//' | sort > "$STATE_DIR/current_mods_sorted.txt" local has_changes=false if [[ -f "$STATE_DIR/mods.json" && -f "$STATE_DIR/gunpacks.json" ]]; then if ! cmp -s "$STATE_DIR/current_mods_sorted.txt" "$STATE_DIR/mods.json"; then log "Mod list has changed" has_changes=true else log "Mod list unchanged" fi log "Checking gunpacks for changes" has_changes=true else log "No previous state found, treating as initial run" has_changes=true fi if [[ "$has_changes" == true ]]; then log "Changes detected, updating modpack" cp "$STATE_DIR/current_mods_sorted.txt" "$STATE_DIR/mods.json" 2>/dev/null || true ls -1 "$TACCZ_DIR"/*.zip 2>/dev/null | xargs -I{} basename {} > "$STATE_DIR/gunpacks.json" || echo "" > "$STATE_DIR/gunpacks.json" local current_version current_version=$(get_current_version) local new_version new_version=$(increment_version "$current_version") log "Version update: $current_version -> $new_version" # Sync actual files to truemods and truegunpacks directories log "Syncing mod files to truemods directory" sync_mods "$STATE_DIR/mods.json" log "Syncing gunpack files to truegunpacks directory" sync_gunpacks "$STATE_DIR/gunpacks.json" # Create Modrinth index create_modrinth_index "$new_version" "$STATE_DIR/mods.json" "$STATE_DIR/gunpacks.json" echo "$new_version" > "$VERSION_FILE" log "Updating git repository" git add "$MODRINTH_INDEX" "$VERSION_FILE" "$STATE_DIR/mods.json" "$STATE_DIR/gunpacks.json" git add "$TRUEMODS_DIR/"* "$TRUEGUNPACKS_DIR/"* 2>/dev/null || true if ! git diff --cached --quiet; then git commit -m "Update modpack to version $new_version" log "Pushing to remote repository" git push origin main log "Successfully pushed version $new_version" else log "No changes to commit" fi else log "No changes detected, skipping update" fi log "Modpack synchronization completed" } main "$@"