mods_list.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #!/bin/bash
  2. # LGSM mods_list.sh function
  3. # Author: Daniel Gibbs
  4. # Contributor: UltimateByte
  5. # Website: https://gameservermanagers.com
  6. # Description: Lists and defines available mods for LGSM supported servers.
  7. # Usage: To add a mod, you just need to add an array variable into fn_mods_info following the guide to set proper values.
  8. # Usage: Then add this array to the mods_global_array.
  9. # Usage: If needed, you can scrape to define the download URL inside the fn_mods_scrape_urls function.
  10. local commandname="MODS"
  11. local commandaction="List Mods"
  12. local function_selfname="$(basename $(readlink -f "${BASH_SOURCE[0]}"))"
  13. check.sh
  14. ## Useful variables
  15. # Files and Directories
  16. modstmpdir="${tmpdir}/mods"
  17. modsdatadir="${lgsmdir}/data/mods"
  18. modslockfile="installed-mods-listing"
  19. modslockfilefullpath="${modsdatadir}/${modslockfile}"
  20. # Separator name
  21. modseparator="MOD"
  22. # Define mods information (required)
  23. fn_mods_info(){
  24. # REQUIRED: mod_info_name=( MOD "modcommand" "Pretty Name" "URL" "filename" "modsubfolders" "LowercaseOn/Off" "/files/to/keep;" "/install/path" "ENGINES" "GAMES" "NOTGAMES" "AUTHOR_URL" "Short Description" )
  25. # Example 1) Well made mod: mod_info_name=( MOD "awesomemod" "This is an Awesome Mod" "https://awesomemod.com/latest.zip" "awesomemod.zip" "0" "LowercaseOff" "OVERWRITE" "${systemdir}/addons" "source;unity3d;" "GAMES" "NOTGAMES" "https://awesomemod.com/" "This mod knows that 42 is the answer" )
  26. # Example 2) Poorly made mod: mod_info_name=( MOD "stupidmod" "This is a stupid mod" "${crappymodurl}" "StupidMod.zip" "2" "LowercaseOn" "cfg;data/crappymod;" "${systemdir}" "source;" "GAMES" "Garry's mod;Counter-Strike: Source;" "This mod is dumber than dumb" )
  27. # None of those values can be empty
  28. # [index] | Usage
  29. # [0] | MOD: separator, all mods must begin with it
  30. # [1] | "modcommand": the LGSM name and command to install the mod (must be unique and lowercase)
  31. # [2] | "Pretty Name": the common name people use to call the mod that will be displayed to the user
  32. # [3] | "URL": link to the file; can be a variable defined in fn_mods_nasty_urls (make sure curl can download it)
  33. # [4] | "filename": the output filename
  34. # [5] | "modsubfolders": in how many subfolders is the mod (none is 1)
  35. # [6] | "LowercaseOn/Off": LowercaseOff or LowercaseOn: enable/disable converting extracted files and directories to lowercase (some games require it)
  36. # [7] | "modinstalldir": the directory in which to install the mode ( use LGSM dir variables such as ${systemdir})
  37. # [8] | "/files/to/keep;", files & directories that should not be overwritten upon update, separated and ended with a semicolon; you can also use "OVERWRITE" to ignore the value or "NOUPDATE" to disallow updating
  38. # [9] | "Supported Engines;": list them according to LGSM ${engine} variables, separated and ended with a semicolon, or use ENGINES to ignore the value
  39. # [10] | "Supported Games;": list them according to LGSM ${gamename} variables, separated and ended with a semicolon, or use GAMES to ignore the value
  40. # [11] | "Unsupported Games;": list them according to LGSM ${gamename} variables, separated and ended with a semicolon, or use NOTGAMES to ignore the value (useful to exclude a game when using Supported Engines)
  41. # [12] | "AUTHOR_URL" is the author's website, displayed to the user when chosing mods to install
  42. # [13] | "Short Description" a description showed to the user upon installation
  43. # Source mods
  44. mod_info_metamod=( MOD "metamod" "MetaMod" "${metamodurl}" "${metamodlatestfile}" "0" "LowercaseOff" "${systemdir}" "OVERWRITE" "source;" "GAMES" "Garry's Mod;" "https://www.sourcemm.net" "Plugins Framework" )
  45. mod_info_sourcemod=( MOD "sourcemod" "SourceMod" "${sourcemodurl}" "${sourcemodlatestfile}" "0" "LowercaseOff" "${systemdir}" "cfg;" "source;" "GAMES" "Garry's Mod;" "http://www.sourcemod.net" "Admin Features (requires MetaMod)" )
  46. # Garry's Mod Addons
  47. mod_info_ulib=( MOD "ulib" "ULib" "https://codeload.github.com/TeamUlysses/ulib/zip/master" "ulib-master.zip" "0" "LowercaseOff" "${systemdir}/addons" "OVERWRITE" "ENGINES" "Garry's Mod;" "NOTGAMES" "http://ulyssesmod.net" "Complete Framework" )
  48. mod_info_ulx=( MOD "ulx" "ULX" "https://codeload.github.com/TeamUlysses/ulx/zip/master" "ulx-master.zip" "0" "LowercaseOff" "${systemdir}/addons" "OVERWRITE" "ENGINES" "Garry's Mod;" "NOTGAMES" "http://ulyssesmod.net" "Admin Panel (requires ULib)" )
  49. mod_info_utime=( MOD "utime" "UTime" "https://github.com/TeamUlysses/utime/archive/master.zip" "utime-master.zip" "0" "LowercaseOff" "${systemdir}/addons" "OVERWRITE" "ENGINES" "Garry's Mod;" "NOTGAMES" "http://ulyssesmod.net" "Keep track of players play time" )
  50. mod_info_uclip=( MOD "uclip" "UClip" "https://github.com/TeamUlysses/uclip/archive/master.zip" "uclip-master.zip" "0" "LowercaseOff" "${systemdir}/addons" "OVERWRITE" "ENGINES" "Garry's Mod;" "NOTGAMES" "http://ulyssesmod.net" "An alternative to noclip" )
  51. mod_info_acf=( MOD "acf" "Armoured Combat Framework" "https://github.com/nrlulz/ACF/archive/master.zip" "acf-master.zip" "0" "LowercaseOn" "${systemdir}/addons" "OVERWRITE" "ENGINES" "Garry's Mod;" "NOTGAMES" "https://github.com/nrlulz/ACF" "Realistic Wepons & Engines" )
  52. mod_info_acf_missiles=( MOD "acfmissiles" "ACF Missiles" "https://github.com/Bubbus/ACF-Missiles/archive/master.zip" "acf-missiles-master.zip" "0" "LowercaseOn" "${systemdir}/addons" "OVERWRITE" "ENGINES" "Garry's Mod;" "NOTGAMES" "https://github.com/Bubbus/ACF-Missiles" "More missiles for ACF" )
  53. mod_info_acf_advdupe2=( MOD "advdupe2" "Advanced Duplicator 2" "https://github.com/wiremod/advdupe2/archive/master.zip" "advdupe2-master.zip" "0" "LowercaseOn" "${systemdir}/addons" "OVERWRITE" "ENGINES" "Garry's Mod;" "NOTGAMES" "http://www.wiremod.com" "Save your constructions" )
  54. mod_info_darkrp=( MOD "darkrp" "DarkRP" "https://github.com/FPtje/DarkRP/archive/master.zip" "darkrp-master.zip" "0" "LowercaseOn" "${systemdir}/addons" "OVERWRITE" "ENGINES" "Garry's Mod;" "NOTGAMES" "http://darkrp.com" "Most popular gamemode" )
  55. mod_info_darkrpmodification=( MOD "darkrpmodification" "DarkRP Modification" "https://github.com/FPtje/darkrpmodification/archive/master.zip" "darkrpmodification-master.zip" "0" "LowercaseOff" "${systemdir}/addons" "NOUPDATE" "ENGINES" "Garry's Mod;" "NOTGAMES" "http://darkrp.com" "Customize DarkRP settings" )
  56. # Oxidemod
  57. mod_info_rustoxide=( MOD "rustoxide" "Oxide for Rust" "https://raw.githubusercontent.com/OxideMod/Snapshots/master/Oxide-Rust.zip" "Oxide-Rust_Linux.zip" "0" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Rust;" "NOTGAMES" "http://oxidemod.org/downloads/oxide-for-rust.1659" "Allows for the use of plugins" )
  58. mod_info_hwoxide=( MOD "hwoxide" "Oxide for Hurtworld" "https://raw.githubusercontent.com/OxideMod/Snapshots/master/Oxide-Hurtworld.zip" "Oxide-Hurtworld_Linux.zip" "0" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Hurtworld;" "NOTGAMES" "http://oxidemod.org/downloads/oxide-for-hurtworld.1332" "Allows for the use of plugins" )
  59. mod_info_sdtdoxide=( MOD "sdtdoxide" "Oxide for 7 Days To Die" "https://raw.githubusercontent.com/OxideMod/Snapshots/master/Oxide-7DaysToDie.zip" "Oxide-7DaysToDie_Linux.zip" "0" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "7 Days To Die;" "NOTGAMES" "http://oxidemod.org/downloads/oxide-for-7-days-to-die.813" "Allows for the use of plugins" )
  60. # REQUIRED: Set all mods info into one array for convenience
  61. mods_global_array=( "${mod_info_metamod[@]}" "${mod_info_sourcemod[@]}" "${mod_info_ulib[@]}" "${mod_info_ulx[@]}" "${mod_info_utime[@]}" "${mod_info_uclip[@]}" "${mod_info_acf[@]}" "${mod_info_acf_missiles[@]}" "${mod_info_acf_sweps[@]}" "${mod_info_advdupe2[@]}" "${mod_info_darkrp[@]}" "${mod_info_darkrpmodification[@]}" "${mod_info_rustoxide[@]}" "${mod_info_hwoxide[@]}" "${mod_info_sdtdoxide[@]}" )
  62. }
  63. # Get a proper URL for mods that don't provide a good one (optional)
  64. fn_mods_scrape_urls(){
  65. # Metamod
  66. metamodscrapeurl="http://www.gsptalk.com/mirror/sourcemod"
  67. metamodlatestfile="$(wget "${metamodscrapeurl}/?MD" -q -O -| grep "mmsource" | grep "\-linux" | head -n1 | awk -F '>' '{ print $3 }' | awk -F '<' '{ print $1}')"
  68. metamodfasterurl="http://cdn.probablyaserver.com/sourcemod/"
  69. metamodurl="${metamodfasterurl}/${metamodlatestfile}"
  70. # Sourcemod
  71. sourcemodmversion="1.8"
  72. sourcemodscrapeurl="http://www.gsptalk.com/mirror/sourcemod"
  73. sourcemodlatestfile="$(wget "${sourcemodscrapeurl}/?MD" -q -O -| grep "sourcemod-" | grep "\-linux" | head -n1 | awk -F '>' '{ print $3 }' | awk -F '<' '{ print $1}')"
  74. sourcemodfasterurl="http://cdn.probablyaserver.com/sourcemod/"
  75. sourcemodurl="${sourcemodfasterurl}/${sourcemodlatestfile}"
  76. }
  77. # Sets some gsm requirements
  78. fn_gsm_requirements(){
  79. # If tmpdir variable doesn't exist, LGSM is too old
  80. if [ -z "${tmpdir}" ]||[ -z "${lgsmdir}" ]; then
  81. fn_print_fail "Your LGSM version is too old."
  82. echo " * Please do a full update, including ${selfname} script."
  83. core_exit.sh
  84. fi
  85. }
  86. # Define all variables from a mod at once when index is set to a separator
  87. fn_mod_info(){
  88. # If for some reason no index is set, none of this can work
  89. if [ -z "$index" ]; then
  90. fn_print_error "index variable not set. Please report an issue to LGSM Team."
  91. echo "* https://github.com/GameServerManagers/LinuxGSM/issues"
  92. core_exit.sh
  93. fi
  94. modcommand="${mods_global_array[index+1]}"
  95. modprettyname="${mods_global_array[index+2]}"
  96. modurl="${mods_global_array[index+3]}"
  97. modfilename="${mods_global_array[index+4]}"
  98. modsubfolders="${mods_global_array[index+5]}"
  99. modlowercase="${mods_global_array[index+6]}"
  100. modinstalldir="${mods_global_array[index+7]}"
  101. modkeepfiles="${mods_global_array[index+8]}"
  102. modengines="${mods_global_array[index+9]}"
  103. modgames="${mods_global_array[index+10]}"
  104. modexcludegames="${mods_global_array[index+11]}"
  105. modsite="${mods_global_array[index+12]}"
  106. moddescription="${mods_global_array[index+13]}"
  107. }
  108. # Find out if a game is compatible with a mod from a modgames (list of games supported by a mod) variable
  109. fn_compatible_mod_games(){
  110. # Reset test value
  111. modcompatiblegame="0"
  112. # If value is set to GAMES (ignore)
  113. if [ "${modgames}" != "GAMES" ]; then
  114. # How many games we need to test
  115. gamesamount="$(echo "${modgames}" | awk -F ';' '{ print NF }')"
  116. # Test all subvalue of "modgames" using the ";" separator
  117. for ((gamevarindex=1; gamevarindex < ${gamesamount}; gamevarindex++)); do
  118. # Put current game name into modtest variable
  119. gamemodtest="$( echo "${modgames}" | awk -F ';' -v x=${gamevarindex} '{ print $x }' )"
  120. # If game name matches
  121. if [ "${gamemodtest}" == "${gamename}" ]; then
  122. # Mod is compatible !
  123. modcompatiblegame="1"
  124. fi
  125. done
  126. fi
  127. }
  128. # Find out if an engine is compatible with a mod from a modengines (list of engines supported by a mod) variable
  129. fn_compatible_mod_engines(){
  130. # Reset test value
  131. modcompatibleengine="0"
  132. # If value is set to ENGINES (ignore)
  133. if [ "${modengines}" != "ENGINES" ]; then
  134. # How many engines we need to test
  135. enginesamount="$(echo "${modengines}" | awk -F ';' '{ print NF }')"
  136. # Test all subvalue of "modengines" using the ";" separator
  137. for ((gamevarindex=1; gamevarindex < ${enginesamount}; gamevarindex++)); do
  138. # Put current engine name into modtest variable
  139. enginemodtest="$( echo "${modengines}" | awk -F ';' -v x=${gamevarindex} '{ print $x }' )"
  140. # If engine name matches
  141. if [ "${enginemodtest}" == "${engine}" ]; then
  142. # Mod is compatible !
  143. modcompatibleengine="1"
  144. fi
  145. done
  146. fi
  147. }
  148. # Find out if a game is not compatible with a mod from a modnotgames (list of games not supported by a mod) variable
  149. fn_not_compatible_mod_games(){
  150. # Reset test value
  151. modeincompatiblegame="0"
  152. # If value is set to NOTGAMES (ignore)
  153. if [ "${modexcludegames}" != "NOTGAMES" ]; then
  154. # How many engines we need to test
  155. excludegamesamount="$(echo "${modexcludegames}" | awk -F ';' '{ print NF }')"
  156. # Test all subvalue of "modexcludegames" using the ";" separator
  157. for ((gamevarindex=1; gamevarindex < ${excludegamesamount}; gamevarindex++)); do
  158. # Put current engine name into modtest variable
  159. excludegamemodtest="$( echo "${modexcludegames}" | awk -F ';' -v x=${gamevarindex} '{ print $x }' )"
  160. # If engine name matches
  161. if [ "${excludegamemodtest}" == "${gamename}" ]; then
  162. # Mod is compatible !
  163. modeincompatiblegame="1"
  164. fi
  165. done
  166. fi
  167. }
  168. # Sums up if a mod is compatible or not with modcompatibility=0/1
  169. fn_mod_compatible_test(){
  170. # Test game and engine compatibility
  171. fn_compatible_mod_games
  172. fn_compatible_mod_engines
  173. fn_not_compatible_mod_games
  174. if [ "${modeincompatiblegame}" == "1" ]; then
  175. modcompatibility="0"
  176. elif [ "${modcompatibleengine}" == "1" ]||[ "${modcompatiblegame}" == "1" ]; then
  177. modcompatibility="1"
  178. else
  179. modcompatibility="0"
  180. fi
  181. }
  182. # Checks if a mod is compatibile for installation
  183. # Provides available mods for installation
  184. # Provides commands for mods installation
  185. fn_mods_available(){
  186. # First, reset variables
  187. compatiblemodslist=()
  188. availablemodscommands=()
  189. modprettynamemaxlength="0"
  190. modsitemaxlength="0"
  191. moddescriptionmaxlength="0"
  192. modcommandmaxlength="0"
  193. # Find compatible games
  194. # Find separators through the global array
  195. for ((index="0"; index <= ${#mods_global_array[@]}; index++)); do
  196. # If current value is a separator; then
  197. if [ "${mods_global_array[index]}" == "${modseparator}" ]; then
  198. # Set mod variables
  199. fn_mod_info
  200. # Test if game is compatible
  201. fn_mod_compatible_test
  202. # If game is compatible
  203. if [ "${modcompatibility}" == "1" ]; then
  204. # Put it into the list to display to the user
  205. compatiblemodslist+=( "${modprettyname}" "${modcommand}" "${modsite}" "${moddescription}" )
  206. # Keep available commands in an array
  207. availablemodscommands+=( "${modcommand}" )
  208. fi
  209. fi
  210. done
  211. }
  212. # Output available mods in a nice way to the user
  213. fn_mods_show_available(){
  214. # Set and reset vars
  215. compatiblemodslistindex=0
  216. spaces=" "
  217. # As long as we're within index values
  218. while [ "${compatiblemodslistindex}" -lt "${#compatiblemodslist[@]}" ]; do
  219. # Set values for convenience
  220. displayedmodname="${compatiblemodslist[compatiblemodslistindex]}"
  221. displayedmodcommand="${compatiblemodslist[compatiblemodslistindex+1]}"
  222. displayedmodsite="${compatiblemodslist[compatiblemodslistindex+2]}"
  223. displayedmoddescription="${compatiblemodslist[compatiblemodslistindex+3]}"
  224. # Output mods to the user
  225. echo -e "\e[1m${displayedmodname}\e[0m - ${displayedmoddescription} - ${displayedmodsite}"
  226. echo -e " * \e[36m${displayedmodcommand}\e[0m"
  227. # Increment index from the amount of values we just displayed
  228. let "compatiblemodslistindex+=4"
  229. done
  230. # If no mods are found
  231. if [ -z "${compatiblemodslist}" ]; then
  232. fn_print_fail "No mods are currently available for ${gamename}."
  233. core_exit.sh
  234. fi
  235. }
  236. # Get details of a mod any (relevant and unique, such as full mod name or install command) value
  237. fn_mod_get_info_from_command(){
  238. # Variable to know when job is done
  239. modinfocommand="0"
  240. # Find entry in global array
  241. for ((index=0; index <= ${#mods_global_array[@]}; index++)); do
  242. # When entry is found
  243. if [ "${mods_global_array[index]}" == "${currentmod}" ]; then
  244. # Go back to the previous "MOD" separator
  245. for ((index=index; index <= ${#mods_global_array[@]}; index--)); do
  246. # When "MOD" is found
  247. if [ "${mods_global_array[index]}" == "MOD" ]; then
  248. # Get info
  249. fn_mod_info
  250. modinfocommand="1"
  251. break
  252. fi
  253. done
  254. fi
  255. # Exit the loop if job is done
  256. if [ "${modinfocommand}" == "1" ]; then
  257. break
  258. fi
  259. done
  260. }
  261. fn_gsm_requirements
  262. fn_mods_scrape_urls
  263. fn_mods_info
  264. fn_mods_available