diff --git a/.env b/.env index b882b40..2aafca9 100644 --- a/.env +++ b/.env @@ -1,3 +1,7 @@ SERVER_GAME="minetest" -SERVER_MODS="i3;animalia" +# Must be specified like , i.e. mt-mods/i3, separated by a semicolon (;) +# Example: +# SERVER_MODS="mt-mods/i3;ElCeejo/animalia" +# SERVER_MODS="ElCeejo/animalia" +SERVER_MODS="mt-mods/technic_plus_beta" API_URL="https://content.minetest.net/api" \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index ce83b91..7b1265f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN echo "Building image with gameid: $gameid" #Update RUN apt update -y && apt upgrade -y -RUN apt install -y wget curl unzip git g++ make libc6-dev cmake libpng-dev libjpeg-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev libzstd-dev libluajit-5.1-dev gettext libsdl2-dev +RUN apt install -y tmux wget curl unzip git g++ make libc6-dev cmake libpng-dev libjpeg-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev libzstd-dev libluajit-5.1-dev gettext libsdl2-dev libncurses5-dev #Install minetest RUN useradd -ms /bin/bash minetest @@ -17,7 +17,7 @@ WORKDIR /home/minetest RUN git clone --depth 1 https://github.com/minetest/minetest.git minetest-source RUN mkdir /home/minetest/minetest-source/build WORKDIR /home/minetest/minetest-source/build -RUN cmake -DBUILD_SERVER=TRUE -DBUILD_CLIENT=FALSE -DENABLE_CURL=ON -DENABLE_CURSES=ON -DENABLE_POSTGRES=ON -DENABLE_SOUND=OFF .. +RUN cmake -DBUILD_SERVER=TRUE -DBUILD_CLIENT=FALSE -DENABLE_CURL=ON -DENABLE_CURSES=ON -DENABLE_POSTGRES=ON -DENABLE_SOUND=OFF.. RUN make -j 6 USER root WORKDIR /home/minetest/minetest-source/build @@ -25,8 +25,11 @@ RUN make install RUN mkdir -p /usr/local/share/minetest/games +# USER root +# ENTRYPOINT ["bash"] + USER minetest EXPOSE 30000/udp -RUN echo "#!/bin/bash\n/usr/local/bin/minetestserver --gameid $gameid" > ./entrypoint.sh +RUN echo "#!/bin/bash\n/usr/local/bin/minetestserver --gameid $gameid --terminal" > ./entrypoint.sh RUN chmod +x entrypoint.sh ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file diff --git a/install.sh b/install.sh index 3daa7d4..1eab234 100755 --- a/install.sh +++ b/install.sh @@ -1,86 +1,227 @@ #!/usr/bin/env bash -source ./server.env +source ./.env # 1 = json of the game download_and_install_game() { download_url=$(echo "${1}" | jq ".url" | tr -d '"') - cd games + cd games || exit wget -O game.zip "${download_url}" unzip game.zip + rm game.zip cd ../ # data } -get_dependencies - mkdir -p data/games -cd data +cd data || exit +# All mods with their dependencies +calculated_dependencies=() + #Checking for input if [[ $SERVER_MODS == "" || $SERVER_GAME == "" ]]; then echo "Please, fill server.env file before launching this script!" - exit -1 + exit 1 fi #Parsing mode names oIFS="$IFS" IFS=";" -SERVER_MODS=($SERVER_MODS) +SERVER_MODS=("$SERVER_MODS") IFS="$oIFS" #Downloading game results=$(curl --silent -X GET "$API_URL/packages/?type=game&q=$SERVER_GAME") oIFS="$IFS" IFS=$'\n' -authors=($(echo $results | jq '.[].author')) +mapfile -t authors < <(echo "$results" | jq '.[].author') IFS="$oIFS" result_amount="${#authors[@]}" -for i in $(seq 0 $((${result_amount}-1))); do - author=$(echo $results | jq ".[${i}].author" | tr -d '"') - name=$(echo $results | jq ".[${i}].name" | tr -d '"') - desc=$(echo $results | jq ".[${i}].short_description" | tr -d '"') +for i in $(seq 0 $((result_amount-1))); do + author=$(echo "$results" | jq ".[${i}].author" | tr -d '"') + name=$(echo "$results" | jq ".[${i}].name" | tr -d '"') + desc=$(echo "$results" | jq ".[${i}].short_description" | tr -d '"') echo "{${i}} [${author}] (${name}): ${desc}" done chosen="" -while [ true ] +while true do - read answer + read -r answer - chosen=$(echo $results | jq ".[${answer}]") + chosen=$(echo "$results" | jq ".[${answer}]") - if [[ $chosen = null ]]; then + if [[ "$chosen" = null ]]; then echo "Incorrect answer. Try again" else break fi done -chosen_author=$(echo $chosen | jq ".author" | tr -d '"') -chosen_packet_name=$(echo $chosen | jq ".name" | tr -d '"') -request_url="${API_URL}/packages/${chosen_author}/${chosen_packet_name}" +chosen_author=$(echo "$chosen" | jq ".author" | tr -d '"') +chosen_packet_name=$(echo "$chosen" | jq ".name" | tr -d '"') +request_url="${API_URL}/packages/${chosen_author}/${chosen_packet_name}/" -chosen=$(curl --silent -X GET $API_URL/packages/${chosen_author}/${chosen_packet_name}/) +chosen_game=$(curl --silent -X GET "$request_url") + +# download_and_install_game "${chosen_game}" + +gameid=$(echo "$chosen_game" | jq ".author" | tr -d '"') +gameid="$gameid/$(echo "$chosen_game" | jq ".name" | tr -d '"')" + +# 1 = mod id + +is_game () { + type=$(curl --silent -X GET "$API_URL/packages/{$1}/" | jq ".type" | tr -d '"') + if [[ $type = "mod" ]]; then + echo "false" + else + echo "true" + fi +} + +# 1 = mod id +get_dependencies () { + # declare -a calculated_dependencies + echo Checking deps for "$1" + deps=$(curl --silent -X GET "$API_URL/packages/${1}/dependencies/") + deps=$(echo "$deps" | jq ".\"${1}\"") + mapfile -t deps_array < <(echo "$deps" | jq ".[] | length") + amount_of_deps="${#deps_array[@]}" + + if [ "$amount_of_deps" -eq 0 ]; then + echo "No deps for mod" + return + fi + + for (( i = 0 ; i < amount_of_deps-1 ; i++ )); do + #Parse info about dependency + dependency=$(echo "$deps" | jq ".[${i}]") + dependency_name=$(echo "$dependency" | jq ".name") + is_optional=$(echo "$dependency" | jq ".is_optional") + possible_candidates=$(echo "${dependency}" | jq ".packages") + possible_candidates_amount=$(echo "${possible_candidates}" | jq "length") + + #Checking if the dependency was already satisfied + calculated_dependencies_amount=${#calculated_dependencies[@]} + + dependency_satisfied_with_game=false + # for j in $(seq 0 $((possible_candidates_amount-1))); do + for (( j = 0 ; j < possible_candidates_amount-1 ; j++ )); do + current_candidate=$(echo "$possible_candidates" | jq ".[${j}]" | tr -d '"') + # possible_candidates_amount=$(echo "${possible_candidates}" | jq "length") + if [[ $possible_candidates_amount -eq 1 ]]; then + break + fi + + #Check if candidate is the game that is installed + if [[ "$current_candidate" == "$gameid" ]]; then + # echo Dependencies satisfied with game + dependency_satisfied_with_game=true + break + fi + + #Check if candidate is game that is not installed + if [ "$(is_game "$current_candidate")" = "true" ] && [ "$current_candidate" != "$gameid" ]; then + + if [ "${current_candidate}" = "" ] || [ "${current_candidate}" = "null" ]; then + continue; + fi + + possible_candidates=$(echo "$possible_candidates" | jq "del(.[] | select( . == \"${current_candidate}\"))") + j=$((j-1)) + fi + done + + possible_candidates_amount=$(echo "${possible_candidates}" | jq "length") + if [[ $possible_candidates_amount = "" ]]; then + possible_candidates_amount=0 + fi + if [[ "$dependency_satisfied_with_game" = true ]]; then + continue + fi + + # Check whether one of possible candidates as a dependency was already calculated + if (( "$calculated_dependencies_amount" > 0 )); then + for k in $(seq 0 $((calculated_dependencies_amount-1))); do + for h in $(seq 0 $((possible_candidates_amount-1))); do + if [[ "${calculated_dependencies[$k]}" == "${possible_candidates[$h]}" ]]; then + continue + fi + done + done + + # If there's only one candidate for that dependency, then install it without user's confirmation + fi + if (( possible_candidates_amount == 0 )); then + continue + fi + if (( possible_candidates_amount == 1)); then + candidate=$(echo "${possible_candidates[0]}" | jq ".[0]" | tr -d '"') + calculated_dependencies+=("${candidate}") + continue + fi + + got_appropriate_answer=false + + while [ $got_appropriate_answer != true ]; do + # If dep. is optional you can refuse it + if [[ "$is_optional" = false ]]; then + echo "Mod ${1} requires dependency ${dependency_name}." + else + echo "Mod ${1} asks for an optional dependency ${dependency_name}." + echo "(-1) TO CANCEL THIS DEPENDENCY" + fi + + for j in $(seq 0 $((possible_candidates_amount-1))); do + echo \("${j}"\) ["$(echo "$possible_candidates" | jq ".[${j}]")"] + done + printf "> " + read -r chose + + if [ "$is_optional" = false ]; then + if [ "$chose" != $((chose)) ] || [ "$chose" -lt 0 ] || [ "$chose" -gt "$possible_candidates_amount" ]; then + echo "Incorrect answer. Please, try again" + continue + else + got_appropriate_answer=true + fi + else + if [ "$chose" != $((chose)) ]; then + echo "Incorrect answer. Please, try again" + else + got_appropriate_answer=true + fi + fi + done + + + if [ "$chose" = "-1" ] && [ "$is_optional" = true ]; then + continue + fi + chosen=$(echo "$possible_candidates" | jq ".[${chose}]") + if [[ ${calculated_dependencies[*]} =~ $chosen ]]; then + continue + else + calculated_dependencies+=("$chosen") + fi + done +} -download_and_install_game "${chosen}" #Downloading mods -#Array to store aaaaaall the mods to be installed, including their dependencies, dependencies of their dependencies, etc... +#Array to store mods that was required by user mods_to_install=("") oIFS="$IFS" IFS=";" -mods_to_install=($SERVER_MODS) +read -r -a mods_to_install <<< "$SERVER_MODS" IFS="$oIFS" -#TODO: -#1. Iterate over all mods in an array -#2. For every mod, check all deps. (including required and optional) -#3. Ask for required deps, i.e. -# 3.1 Check for satisfied deps and dont touch them (user has specified them in .env, SERVER_MODS) -# 3.2 Check for unsatisfiend deps and give user a list of possible candidates for that dep. -# 3.2.1 go to step 3, treating a dependency as a mod. -# 3.3 Check for optional deps, as user if they want to install these, "-1" or "no(t)" if they dont want to and number of package to install -#4. Download all mods for array formed during these steps \ No newline at end of file +asked_mods_amount=${#mods_to_install[@]} +for i in $(seq 0 $((asked_mods_amount-1))); do + get_dependencies "${mods_to_install[${i}]}" +done +echo "Result: ${calculated_dependencies[*]}"