diff --git a/lgsm/modules/command_mods_install.sh b/lgsm/modules/command_mods_install.sh index a8f90293b2..1a0f25119c 100755 --- a/lgsm/modules/command_mods_install.sh +++ b/lgsm/modules/command_mods_install.sh @@ -109,6 +109,11 @@ if [ -f "${modsinstalledlistfullpath}" ]; then fi ## Installation. +# CounterStrikeSharp requires Metamod:Source 2.0. +if [ "${modcommand}" == "counterstrikesharp" ]; then + fn_mod_exist "metamodsource2" +fi + # If amxmodx check if metamod exists first if [ "${modcommand}" == "amxmodx" ]; then fn_mod_exist "metamod" @@ -133,6 +138,11 @@ fn_mod_add_list fn_mod_tidy_files_list fn_mods_clear_tmp_dir +# Install the Metamod:Source search path for CS2. +if [ "${modcommand}" == "metamodsource2" ]; then + fn_mod_install_gameinfo_gi_file +fi + # Create/modify existing liblist.gam file for Metamod if [ "${modcommand}" == "metamod" ]; then fn_mod_install_liblist_gam_file diff --git a/lgsm/modules/command_mods_remove.sh b/lgsm/modules/command_mods_remove.sh index 04240eb60d..c9c06b15f0 100755 --- a/lgsm/modules/command_mods_remove.sh +++ b/lgsm/modules/command_mods_remove.sh @@ -151,6 +151,11 @@ if [ "${engine}" == "unity3d" ] && [[ "${modprettyname}" == *"Oxide"* ]]; then unset exitbypass fi +# Remove the Metamod:Source search path for CS2. +if [ "${modcommand}" == "metamodsource2" ]; then + fn_mod_remove_gameinfo_gi_file +fi + # Remove/modify existing liblist.gam file for Metamod if [ "${modcommand}" == "metamod" ]; then fn_mod_remove_liblist_gam_file diff --git a/lgsm/modules/command_mods_update.sh b/lgsm/modules/command_mods_update.sh index 10279b67b3..2d1eba650f 100755 --- a/lgsm/modules/command_mods_update.sh +++ b/lgsm/modules/command_mods_update.sh @@ -93,6 +93,10 @@ while [ "${installedmodsline}" -le "${installedmodscount}" ]; do fn_mod_add_list fn_mod_tidy_files_list fn_mods_clear_tmp_dir + # Restore the Metamod:Source search path if a CS2 update removed it. + if [ "${modcommand}" == "metamodsource2" ]; then + fn_mod_install_gameinfo_gi_file + fi fi ((installedmodsline++)) else diff --git a/lgsm/modules/core_getopt.sh b/lgsm/modules/core_getopt.sh index ad09bf1df5..fede1debbf 100755 --- a/lgsm/modules/core_getopt.sh +++ b/lgsm/modules/core_getopt.sh @@ -137,7 +137,7 @@ if [ "${shortname}" == "squad" ]; then fi ## Mods commands. -if [ "${engine}" == "source" ] || [ "${shortname}" == "rust" ] || [ "${shortname}" == "hq" ] || [ "${shortname}" == "sdtd" ] || [ "${shortname}" == "cs" ] || [ "${shortname}" == "dod" ] || [ "${shortname}" == "tfc" ] || [ "${shortname}" == "ns" ] || [ "${shortname}" == "ts" ] || [ "${shortname}" == "hldm" ] || [ "${shortname}" == "vh" ]; then +if [ "${engine}" == "source" ] || [ "${shortname}" == "cs2" ] || [ "${shortname}" == "rust" ] || [ "${shortname}" == "hq" ] || [ "${shortname}" == "sdtd" ] || [ "${shortname}" == "cs" ] || [ "${shortname}" == "dod" ] || [ "${shortname}" == "tfc" ] || [ "${shortname}" == "ns" ] || [ "${shortname}" == "ts" ] || [ "${shortname}" == "hldm" ] || [ "${shortname}" == "vh" ]; then currentopt+=("${cmd_mods_install[@]}" "${cmd_mods_remove[@]}" "${cmd_mods_update[@]}") fi diff --git a/lgsm/modules/mods_core.sh b/lgsm/modules/mods_core.sh index 3a14fcb84a..ac8f25a7b4 100755 --- a/lgsm/modules/mods_core.sh +++ b/lgsm/modules/mods_core.sh @@ -158,6 +158,11 @@ fn_mod_tidy_files_list() { sed -i "/^addons\/metamod\/sourcemod.vdf$/d" "${modsdir}/${modcommand}-files.txt" fi + # Keep Metamod:Source when removing CounterStrikeSharp, but remove its own VDF. + if [ "${modcommand}" == "counterstrikesharp" ]; then + sed -i "/^addons\/metamod$/d" "${modsdir}/${modcommand}-files.txt" + fi + # Remove common paths from deletion list (Add your sourcemod mod here) if [ "${modcommand}" == "gokz" ] || [ "${modcommand}" == "ttt" ] || [ "${modcommand}" == "steamworks" ] || [ "${modcommand}" == "get5" ]; then sed -i "/^addons\/sourcemod$/d" "${modsdir}/${modcommand}-files.txt" @@ -693,6 +698,66 @@ fn_mod_remove_liblist_gam_file() { fi } +# modifiers for gameinfo.gi to add/remove the Metamod:Source search path +# Counter-Strike 2 only: the csgo paths below are specific to that game. +fn_mod_install_gameinfo_gi_file() { + local gameinfofile="${modinstalldir}/gameinfo.gi" + local metamodpattern='^[[:space:]]*"?Game"?[[:space:]]+"?csgo/addons/metamod"?[[:space:]]*(//.*)?$' + local lowviolencepattern='^[[:space:]]*"?Game_LowViolence"?[[:space:]]+"?csgo_lv"?[[:space:]]*(//.*)?$' + + if [ -f "${gameinfofile}" ]; then + # the search path survives a mod update, only add it when it is missing + if grep -Eq "${metamodpattern}" "${gameinfofile}"; then + fn_script_log_info "Metamod:Source search path already set in ${gameinfofile}" + else + # insert the search path below Game_LowViolence as documented by Metamod:Source + logentry="line (Game csgo/addons/metamod) inserted into ${gameinfofile}" + echo -en "adding Metamod:Source search path in gameinfo.gi..." + sed -i -E "\\@${lowviolencepattern}@a\\\\t\\t\\tGame\\tcsgo/addons/metamod" "${gameinfofile}" + grep -Eq "${metamodpattern}" "${gameinfofile}" + exitcode=$? + # if the insert didn't happen, error out + if [ "${exitcode}" -ne 0 ]; then + fn_script_log_fail "${logentry}" + fn_print_fail_eol_nl + core_exit.sh + else + fn_script_log_pass "${logentry}" + fn_print_ok_eol_nl + fi + fi + else + fn_script_log_fail "Unable to find ${gameinfofile}" + fn_print_fail_nl "Unable to find ${gameinfofile}" + core_exit.sh + fi +} + +# Unlike the install counterpart this does not call core_exit.sh on failure: +# command_mods_remove.sh ends with fn_script_log, which leaves exitcode alone, +# while command_mods_install.sh ends with fn_script_log_pass, which resets it to 0. +fn_mod_remove_gameinfo_gi_file() { + local gameinfofile="${modinstalldir}/gameinfo.gi" + local metamodpattern='^[[:space:]]*"?Game"?[[:space:]]+"?csgo/addons/metamod"?[[:space:]]*(//.*)?$' + + if [ -f "${gameinfofile}" ]; then + # is the search path found? If so remove it and keep the rest of the file + if grep -Eq "${metamodpattern}" "${gameinfofile}"; then + logentry="line (Game csgo/addons/metamod) removed from ${gameinfofile}" + echo -en "removing Metamod:Source search path in gameinfo.gi..." + # delete the line we inserted + sed -i -E "\\@${metamodpattern}@d" "${gameinfofile}" + if grep -Eq "${metamodpattern}" "${gameinfofile}"; then + fn_script_log_fail "${logentry}" + fn_print_fail_eol_nl + else + fn_script_log_pass "${logentry}" + fn_print_ok_eol_nl + fi + fi + fi +} + fn_mod_install_amxmodx_file() { # does plugins.ini exist? if [ -f "${modinstalldir}/addons/metamod/plugins.ini" ]; then diff --git a/lgsm/modules/mods_list.sh b/lgsm/modules/mods_list.sh index 39eca5e429..94ac8fceda 100755 --- a/lgsm/modules/mods_list.sh +++ b/lgsm/modules/mods_list.sh @@ -60,6 +60,12 @@ metamodsourcescrapeurl="https://mms.alliedmods.net/mmsdrop/${metamodsourceversio metamodsourcelatestfile=$(wget "${metamodsourcescrapeurl}" -q -O -) metamodsourcedownloadurl="https://www.metamodsource.net/latest.php?os=linux&version=${metamodsourceversion}" metamodsourceurl="${metamodsourcedownloadurl}" +# Metamod:Source 2.0 +metamodsource2version="2.0" +metamodsource2scrapeurl="https://mms.alliedmods.net/mmsdrop/${metamodsource2version}/mmsource-latest-linux" +metamodsource2latestfile=$(wget "${metamodsource2scrapeurl}" -q -O -) +metamodsource2downloadurl="https://www.metamodsource.net/latest.php?os=linux&version=${metamodsource2version}" +metamodsource2url="${metamodsource2downloadurl}" # Sourcemod sourcemodversion="1.13" sourcemodscrapeurl="https://sm.alliedmods.net/smdrop/${sourcemodversion}/sourcemod-latest-linux" @@ -77,6 +83,12 @@ stripperlatestfile="stripper-${stripperversion}-linux.tar.gz" stripperdownloadurl="http://www.bailopan.net/stripper/snapshots/1.2/${stripperlatestfile}" stripperurl="${stripperdownloadurl}" +# CS2 Mods +counterstrikesharprelease=$(curl --connect-timeout 3 -sL https://api.github.com/repos/roflmuffin/CounterStrikeSharp/releases/latest) +counterstrikesharplastbuild=$(printf '%s\n' "${counterstrikesharprelease}" | jq '.assets[]? | select(.name | startswith("counterstrikesharp-with-runtime-linux-") and endswith(".zip"))' 2> /dev/null) +counterstrikesharplatestfile=$(printf '%s\n' "${counterstrikesharplastbuild}" | jq -r '.name') +counterstrikesharplatestlink=$(printf '%s\n' "${counterstrikesharplastbuild}" | jq -r '.browser_download_url') + # CS:GO Mods get5lastbuild=$(curl --connect-timeout 3 -sL https://api.github.com/repos/splewis/get5/releases/latest | jq '.assets[] |select(.browser_download_url | endswith(".tar.gz"))') get5latestfile=$(echo -e "${get5lastbuild}" | jq -r '.name') @@ -157,6 +169,10 @@ mod_info_sourcemod=(MOD "sourcemod" "SourceMod" "${sourcemodurl}" "${sourcemodla mod_info_steamworks=(MOD "steamworks" "SteamWorks" "${steamworksurl}" "${steamworkslatestfile}" "0" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Counter-Strike: Global Offensive;" "NOTGAMES" "https://github.com/KyleSanderson/SteamWorks" "Exposing SteamWorks functions to SourcePawn") mod_info_stripper=(MOD "stripper" "Stripper Source" "${stripperurl}" "${stripperlatestfile}" "0" "LowercaseOff" "${systemdir}" "addons/stripper/maps;" "ENGINES" "Counter-Strike: Global Offensive;Counter-Strike: Source;Day of Defeat: Source;Half Life: Deathmatch;Half Life 2: Deathmatch;Insurgency;Left 4 Dead;Left 4 Dead 2;Nuclear Dawn;Team Fortress 2;" "NOTGAMES" "http://www.bailopan.net/stripper/" "Add or remove objects from map (requires MetaMod)") +# CS2 Mods +mod_info_metamodsource2=(MOD "metamodsource2" "Metamod:Source 2.0" "${metamodsource2url}" "${metamodsource2latestfile}" "0" "LowercaseOff" "${systemdir}" "addons/metamod/metaplugins.ini;" "ENGINES" "Counter-Strike 2;" "NOTGAMES" "https://www.metamodsource.net" "Plugins Framework (Dev Build)") +mod_info_counterstrikesharp=(MOD "counterstrikesharp" "CounterStrikeSharp" "${counterstrikesharplatestlink}" "${counterstrikesharplatestfile}" "0" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Counter-Strike 2;" "NOTGAMES" "https://docs.cssharp.dev/" "Write server plugins in C# (requires Metamod:Source 2.0)") + # CS:GO Mods mod_info_gokz=(MOD "gokz" "GOKZ" "${gokzlatestlink}" "${gokzlatestfile}" "0" "LowercaseOff" "${systemdir}" "cfg;addons/sourcemod/configs;" "ENGINES" "Counter-Strike: Global Offensive;" "NOTGAMES" "https://github.com/KZGlobalTeam/gokz" "GOKZ ${gokzlatestversion} - Implements the KZ game mode (requires SourceMod and MetaMod)") mod_info_ttt=(MOD "ttt" "Trouble in Terrorist Town" "https://csgottt.com/downloads/ttt-latest-dev-${sourcemodversion}.zip" "ttt-latest.zip" "0" "LowercaseOff" "${systemdir}" "cfg;addons/sourcemod/configs;" "ENGINES" "Counter-Strike: Global Offensive;" "NOTGAMES" "https://github.com/Bara/TroubleinTerroristTown" "Implements the TTT game mode (requires SourceMod and MetaMod)") @@ -211,4 +227,4 @@ mod_info_valheimplus=(MOD "valheimplus" "Valheim PLUS" "${valheimpluslatestlink} mod_info_bepinexvh=(MOD "bepinexvh" "BepInEx Valheim" "${bepinexvhlatestlink}" "denikson-BepInExPack_Valheim.zip" "BepInExPack_Valheim" "LowercaseOff" "${systemdir}" "OVERWRITE" "ENGINES" "Valheim;" "NOTGAMES" "https://valheim.thunderstore.io/package/denikson/BepInExPack_Valheim/" "Unity / XNA game patcher and plugin framework") # REQUIRED: Set all mods info into the global array -mods_global_array=("${mod_info_metamod[@]}" "${mod_info_base_amxx[@]}" "${mod_info_cs_amxx[@]}" "${mod_info_dod_amxx[@]}" "${mod_info_tfc_amxx[@]}" "${mod_info_ns_amxx[@]}" "${mod_info_ts_amxx[@]}" "${mod_info_metamodsource[@]}" "${mod_info_sourcemod[@]}" "${mod_info_steamworks[@]}" "${mod_info_gokz[@]}" "${mod_info_ttt[@]}" "${mod_info_get5[@]}" "${mod_info_prac[@]}" "${mod_info_pug[@]}" "${mod_info_dhook[@]}" "${mod_info_movement[@]}" "${mod_info_cleaner[@]}" "${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_pac3[@]}" "${mod_info_wiremod[@]}" "${mod_info_wiremodextras[@]}" "${mod_info_darkrp[@]}" "${mod_info_darkrpmodification[@]}" "${mod_info_rustcarbon[@]}" "${mod_info_rustoxide[@]}" "${mod_info_hwoxide[@]}" "${mod_info_sdtdoxide[@]}" "${mod_info_advduplicator[@]}" "${mod_info_trackassemblytool[@]}" "${mod_info_physpropertiesadv[@]}" "${mod_info_controlsystemse2[@]}" "${mod_info_e2pistontiming[@]}" "${mod_info_propcannontool[@]}" "${mod_info_gearassemblytool[@]}" "${mod_info_spinnertool[@]}" "${mod_info_surfacefrictiontool[@]}" "${mod_info_magneticdipole[@]}" "${mod_info_environmentorganizer[@]}" "${mod_info_precision_alignment[@]}" "${mod_info_improved_stacker[@]}" "${mod_info_improved_weight[@]}" "${mod_info_improved_antinoclip[@]}" "${mod_info_laserstool[@]}" "${mod_info_valheimplus[@]}" "${mod_info_bepinexvh[@]}") +mods_global_array=("${mod_info_metamod[@]}" "${mod_info_base_amxx[@]}" "${mod_info_cs_amxx[@]}" "${mod_info_dod_amxx[@]}" "${mod_info_tfc_amxx[@]}" "${mod_info_ns_amxx[@]}" "${mod_info_ts_amxx[@]}" "${mod_info_metamodsource[@]}" "${mod_info_metamodsource2[@]}" "${mod_info_counterstrikesharp[@]}" "${mod_info_sourcemod[@]}" "${mod_info_steamworks[@]}" "${mod_info_gokz[@]}" "${mod_info_ttt[@]}" "${mod_info_get5[@]}" "${mod_info_prac[@]}" "${mod_info_pug[@]}" "${mod_info_dhook[@]}" "${mod_info_movement[@]}" "${mod_info_cleaner[@]}" "${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_pac3[@]}" "${mod_info_wiremod[@]}" "${mod_info_wiremodextras[@]}" "${mod_info_darkrp[@]}" "${mod_info_darkrpmodification[@]}" "${mod_info_rustcarbon[@]}" "${mod_info_rustoxide[@]}" "${mod_info_hwoxide[@]}" "${mod_info_sdtdoxide[@]}" "${mod_info_advduplicator[@]}" "${mod_info_trackassemblytool[@]}" "${mod_info_physpropertiesadv[@]}" "${mod_info_controlsystemse2[@]}" "${mod_info_e2pistontiming[@]}" "${mod_info_propcannontool[@]}" "${mod_info_gearassemblytool[@]}" "${mod_info_spinnertool[@]}" "${mod_info_surfacefrictiontool[@]}" "${mod_info_magneticdipole[@]}" "${mod_info_environmentorganizer[@]}" "${mod_info_precision_alignment[@]}" "${mod_info_improved_stacker[@]}" "${mod_info_improved_weight[@]}" "${mod_info_improved_antinoclip[@]}" "${mod_info_laserstool[@]}" "${mod_info_valheimplus[@]}" "${mod_info_bepinexvh[@]}")