Skip to content
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
fad8c9c
Fix small Misstake. Shame on me.
desperationfighter Apr 10, 2022
e4b53e5
Added internal Modlist Tab
desperationfighter Apr 10, 2022
8f20346
Change to alphabetical sorted Mod List
desperationfighter Apr 10, 2022
8d11859
integrated deactivated Mod list + improvments
desperationfighter Apr 11, 2022
8f2842b
reduce overhead + clearup appearance
desperationfighter Apr 11, 2022
c035e4a
Merge pull request #1 from desperationfighter/Dev-Desp
desperationfighter Apr 13, 2022
0e0c2ab
Coding consistency cleanup from previous PR
Metious Apr 14, 2022
a125c8d
Better game store checks
Metious Apr 14, 2022
b33e15d
Update QModManager/OptionsManager.cs
desperationfighter Apr 14, 2022
12e4503
Update QModManager/OptionsManager.cs
desperationfighter Apr 14, 2022
59cd0f6
First try of getting the enable disable Check box
desperationfighter Apr 14, 2022
4f0d5a4
First test to implement a List of chaning mods
desperationfighter Apr 17, 2022
c74fbc7
backup
desperationfighter Apr 17, 2022
96c55d8
Onchange Methode cleared up
desperationfighter Apr 17, 2022
1627b32
Adding Apply Function and false confirm prevention
desperationfighter Apr 17, 2022
9694aa0
start writing to disk
desperationfighter Apr 18, 2022
a33d1ef
Save to Mod.json first time working fine
desperationfighter Apr 18, 2022
a88324c
backup
desperationfighter Apr 18, 2022
9cd1e88
Rework Code + Deactivated Mods can now be changed too
desperationfighter Apr 18, 2022
32c377d
Update Pirate Check
desperationfighter Apr 19, 2022
e68a324
Merge pull request #2 from desperationfighter/Dev-Pirate
desperationfighter Apr 19, 2022
2332055
added cancel changes function
desperationfighter Apr 24, 2022
54a8500
code Cleanup
desperationfighter Apr 24, 2022
761d8b2
Merge pull request #3 from desperationfighter/Dev-ChangeModStatus
desperationfighter Apr 24, 2022
acba05c
Added QMM Option Entry to make Mod List Menu optional
desperationfighter Apr 25, 2022
6c767a7
Merge pull request #4 from desperationfighter/Dev-ShowModlistOptional
desperationfighter Apr 25, 2022
1c526f4
Fix for QMM Versionchecker parsing + Fix Gameversion Logger (#5)
desperationfighter May 7, 2022
642d684
Adding API for Mods to get current running QMM Version. (#6)
desperationfighter May 15, 2022
5214db2
Added detailed Error Catch for Folder Tree Logger (#7)
desperationfighter May 25, 2022
dc389ec
additional Error Catching + Mod.json Information on Filetree (#8)
desperationfighter Jun 16, 2022
374f0ec
returnfrom save game warning (#9)
desperationfighter Jun 16, 2022
41ff307
Error Catching for Date and Time Logging.
desperationfighter Jul 20, 2022
d5f7470
pass through Exception Message
desperationfighter Aug 15, 2022
15ebab5
Merge branch 'SubnauticaModding:Dev' into Dev
desperationfighter Sep 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions QModManager/Checks/PirateCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ namespace QModManager.Checks
{
internal static class PirateCheck
{
internal static string Steamapi => "steam_api64.dll";
internal static int Steamapilengh => 220000;


internal static string folder = Environment.CurrentDirectory;
internal const string SteamApiName = "steam_api64.dll";
internal const int SteamApiLength = 220000;
internal static bool PirateDetected;

private static readonly string _folder = Environment.CurrentDirectory;

internal static readonly HashSet<string> CrackedFiles = new HashSet<string>()
{
"steam_api64.cdx",
Expand All @@ -26,18 +25,20 @@ internal static class PirateCheck
"Subnautica_Data/Plugins/steam_emu.ini",
"Profile/SteamUserID.cfg",
"Profile/Stats/Achievements.Bin",
"Profile/VALVE/SteamUserID.cfg",
"Profile/VALVE/Stats/Achievements.Bin",
"launcher.bat",
"chuj.cdx",
};

internal static void IsPirate()
{
string steamDll = Path.Combine(folder, Steamapi);
string steamDll = Path.Combine(_folder, SteamApiName);
bool steamStore = File.Exists(steamDll);
if (steamStore)
{
FileInfo fileInfo = new FileInfo(steamDll);
if (fileInfo.Length > Steamapilengh)
if (fileInfo.Length > SteamApiLength)
{
PirateDetected = true;
}
Expand All @@ -47,15 +48,15 @@ internal static void IsPirate()
{
foreach (string file in CrackedFiles)
{
if (File.Exists(Path.Combine(folder, file)))
if (File.Exists(Path.Combine(_folder, file)))
{
PirateDetected = true;
break;
}
}
}

Logger.Info(PirateDetected? "Ahoy, matey! Ye be a pirate!":"Seems Legit.");
Logger.Info(PirateDetected ? "Ahoy, matey! Ye be a pirate!" : "Seems legit.");
}
}
}
242 changes: 241 additions & 1 deletion QModManager/OptionsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,26 @@
using QModManager.Utility;
using System.Reflection;
using UnityEngine.Events;
using System.Collections.Generic;
using System.Linq;

internal static class OptionsManager
{
internal static int ModsTab;
internal static string ModsListTabName = "QMods List";
internal static int ModListTab;
public static List<QMod> ModListPendingChanges;

[HarmonyPatch(typeof(uGUI_OptionsPanel), nameof(uGUI_OptionsPanel.AddTabs))]
internal static class OptionsPatch
{
[HarmonyPostfix]
internal static void Postfix(uGUI_OptionsPanel __instance)
{
#region Mod Config
ModsTab = __instance.AddTab("Mods");
__instance.AddHeading(ModsTab, "QModManager");


MethodInfo AddToggleOption = null;
if(Patcher.CurrentlyRunningGame == QModGame.Subnautica)
{
Expand Down Expand Up @@ -60,7 +65,242 @@ internal static void Postfix(uGUI_OptionsPanel __instance)
AddToggleOption.Invoke(__instance, new object[] { ModsTab, "Enable debug logs", Config.EnableDebugLogs, new UnityAction<bool>(value => Config.EnableDebugLogs = value), null });
AddToggleOption.Invoke(__instance, new object[] { ModsTab, "Enable developer mode", Config.EnableDevMode, new UnityAction<bool>(value => Config.EnableDevMode = value), null });
}
#endregion Mod Config

#region Mod List
//Start creating Ingame Mod List
Logger.Log(Logger.Level.Debug, "OptionsMenu - Start creating Modlist");

//Reset ModList and Pending Changes on Relead the List Menu - We do not want to save any Data or take over Data from previous time here
ModListPendingChanges = new List<QMod>();
List<QMod> mods = new List<QMod>();
foreach (var iQMod in QModServices.Main.GetAllMods().OrderBy(mod => mod.DisplayName))
if (iQMod is QMod qMod)
mods.Add(qMod);
List<QMod> erroredMods = mods.FindAll(m => !m.IsLoaded && m.Status > 0);
int erroredModscount = erroredMods.Count;
List<QMod> activeMods = new List<QMod>();
List<QMod> inactiveMods = new List<QMod>();

//Create new Tab in the Menu
ModListTab = __instance.AddTab("QMods List");

//Add QMM Informations
#if SUBNAUTICA_STABLE
__instance.AddHeading(ModListTab, $"Running QModManager {Assembly.GetExecutingAssembly().GetName().Version.ToStringParsed()} for Subnautica");
#elif SUBNAUTICA_EXP
__instance.AddHeading(ModListTab, $"Running QModManager -Experimental- {Assembly.GetExecutingAssembly().GetName().Version.ToStringParsed()} for Subnautica");
#elif BELOWZERO_STABLE
__instance.AddHeading(ModListTab, $"Running QModManager {Assembly.GetExecutingAssembly().GetName().Version.ToStringParsed()} for Below Zero");
#elif BELOWZERO_EXP
__instance.AddHeading(ModListTab, $"Running QModManager -Experimental- {Assembly.GetExecutingAssembly().GetName().Version.ToStringParsed()} for Below Zero");
#endif

//Add SML Informations to the Top as its pretty Important
var modprio_sml = QModServices.Main.GetMod("SMLHelper");
if (modprio_sml != null)
{
__instance.AddHeading(ModListTab, $"{modprio_sml.DisplayName} {(modprio_sml.Enable ? $"v{modprio_sml.ParsedVersion}" : string.Empty)} is {(modprio_sml.IsLoaded ? "enabled" : "disabled")}");
}
else
{
__instance.AddHeading(ModListTab, $"SMLHelper is not installed");
}

//Now lets create the Mod List
foreach (var mod in mods)
{
if (mod.Id != "SMLHelper")
{
if (mod.Enable)
{
activeMods.Add(mod);

}
else
{
inactiveMods.Add(mod);
}
}
}

//Now show some Statistics ahead of the List.
__instance.AddHeading(ModListTab, $"- - Statistics - -");
__instance.AddHeading(ModListTab, $"{mods.Count()} Mods found");
if (erroredModscount != 0)
{
__instance.AddHeading(ModListTab, $"WARNING: {erroredModscount} Mods failed to load");
}
__instance.AddHeading(ModListTab, $"{activeMods.Count} Mods enabled");
__instance.AddHeading(ModListTab, $"{inactiveMods.Count} Mods disabled");


//At first show the Mods with errors. But show it only, when Mod errors exist
if (erroredModscount != 0)
{
__instance.AddHeading(ModListTab, $"- - List of Error Mods, You need to take Actions on them ! - -");
foreach (var mod in erroredMods)
{
//This is the Header Entry
//__instance.AddHeading(ModListTab, $"{mod.DisplayName} from {mod.Author}");

//This is the Collapse SubMenu of the Entry
if (Patcher.CurrentlyRunningGame == QModGame.Subnautica)
{
MethodInfo Modlist_AddToggleOption = null;
Modlist_AddToggleOption = typeof(uGUI_OptionsPanel).GetMethod(nameof(AddToggleOption), new System.Type[] { typeof(int), typeof(string), typeof(bool), typeof(UnityAction<bool>) });
#if SUBNAUTICA_STABLE
Modlist_AddToggleOption.Invoke(__instance, new object[] { ModListTab, $"{mod.DisplayName}", mod.Enable, new UnityAction<bool>(value => OnChangeModStatus(mod, value, __instance)) });
#else
Modlist_AddToggleOption.Invoke(__instance, new object[] { ModListTab, $"{mod.DisplayName} from {mod.Author}", mod.Enable, new UnityAction<bool>(value => OnChangeModStatus(mod, value, __instance)) });
#endif
}
else
{
MethodInfo Modlist_AddToggleOption = null;
Modlist_AddToggleOption = typeof(uGUI_OptionsPanel).GetMethod(nameof(AddToggleOption), new System.Type[] { typeof(int), typeof(string), typeof(bool), typeof(UnityAction<bool>), typeof(string) });
Modlist_AddToggleOption.Invoke(__instance, new object[] { ModListTab, $"{mod.DisplayName} from {mod.Author}", mod.Enable, new UnityAction<bool>(value => OnChangeModStatus(mod, value, __instance)), null });
}
}
}

//Now we write down the actull List with all Mods. Starting with the Active Mods
__instance.AddHeading(ModListTab, $"- - List of currently running Mods - -");
foreach (var mod in activeMods)
{
//This is the Header Entry
//__instance.AddHeading(ModListTab, $"{mod.DisplayName} v{mod.ParsedVersion.ToString()} from {mod.Author}");

//This is the Collapse SubMenu of the Entry
if (Patcher.CurrentlyRunningGame == QModGame.Subnautica)
{
MethodInfo Modlist_AddToggleOption = null;
Modlist_AddToggleOption = typeof(uGUI_OptionsPanel).GetMethod(nameof(AddToggleOption), new System.Type[] { typeof(int), typeof(string), typeof(bool), typeof(UnityAction<bool>) });
#if SUBNAUTICA_STABLE
Modlist_AddToggleOption.Invoke(__instance, new object[] { ModListTab, $"{mod.DisplayName}", mod.Enable, new UnityAction<bool>(value => OnChangeModStatus(mod, value, __instance)) });
#else
Modlist_AddToggleOption.Invoke(__instance, new object[] { ModListTab, $"{mod.DisplayName} v{mod.ParsedVersion.ToString()} from {mod.Author}", mod.Enable, new UnityAction<bool>(value => OnChangeModStatus(mod, value, __instance)) });
#endif
}
else
{
MethodInfo Modlist_AddToggleOption = null;
Modlist_AddToggleOption = typeof(uGUI_OptionsPanel).GetMethod(nameof(AddToggleOption), new System.Type[] { typeof(int), typeof(string), typeof(bool), typeof(UnityAction<bool>), typeof(string) });
Modlist_AddToggleOption.Invoke(__instance, new object[] { ModListTab, $"{mod.DisplayName} v{mod.ParsedVersion.ToString()} from {mod.Author}", mod.Enable, new UnityAction<bool>(value => OnChangeModStatus(mod, value, __instance)), null });
}
}

//Continue with Disabled Mods
__instance.AddHeading(ModListTab, $"- - List of Disabled Mods - -");
foreach (var mod in inactiveMods)
{
//This is the Header Entry
//__instance.AddHeading(ModListTab, $"{mod.DisplayName} from {mod.Author}");

//This is the Collapse SubMenu of the Entry
if (Patcher.CurrentlyRunningGame == QModGame.Subnautica)
{
MethodInfo Modlist_AddToggleOption = null;
Modlist_AddToggleOption = typeof(uGUI_OptionsPanel).GetMethod(nameof(AddToggleOption), new System.Type[] { typeof(int), typeof(string), typeof(bool), typeof(UnityAction<bool>) });
#if SUBNAUTICA_STABLE
Modlist_AddToggleOption.Invoke(__instance, new object[] { ModListTab, $"{mod.DisplayName}", mod.Enable, new UnityAction<bool>(value => OnChangeModStatus(mod, value, __instance)) });
#else
Modlist_AddToggleOption.Invoke(__instance, new object[] { ModListTab, $"{mod.DisplayName} from {mod.Author}", mod.Enable, new UnityAction<bool>(value => OnChangeModStatus(mod, value, __instance)) });
#endif
}
else
{
MethodInfo Modlist_AddToggleOption = null;
Modlist_AddToggleOption = typeof(uGUI_OptionsPanel).GetMethod(nameof(AddToggleOption), new System.Type[] { typeof(int), typeof(string), typeof(bool), typeof(UnityAction<bool>), typeof(string) });
Modlist_AddToggleOption.Invoke(__instance, new object[] { ModListTab, $"{mod.DisplayName} from {mod.Author}", mod.Enable, new UnityAction<bool>(value => OnChangeModStatus(mod, value, __instance)), null });
}
}

Logger.Log(Logger.Level.Debug, "OptionsMenu - ModList - Creating Modlist Ending");

#endregion Mod List
}

static void OnChangeModStatus(QMod ChangedMod,bool status, uGUI_OptionsPanel __instance)
{
//write the new Status to the Mod Variable
ChangedMod.Enable = status;

QMod _modexist = new QMod();
//Now check if the Mod is already in the Pending list
try
{
//Is there a better way than try/catch using Find while determind a null or Empty when no Mod is found ?
_modexist = ModListPendingChanges.Find(mdt => mdt.Id == ChangedMod.Id);
}
catch
{
//if not it will result in an exception so i can set it to null
_modexist = null;
}

if (_modexist == null)
{
//if the Mod is not in list add it to pending
try
{
ModListPendingChanges.Add(ChangedMod);
}
catch
{
Logger.Log(Logger.Level.Warn, "OptionsMenu - ModList - Error on Adding Mod to Pending Status Change List");
}
}
else if(_modexist.Id == ChangedMod.Id)
{
//if the Mod is already in the List the user revert the change. Remove it
try
{
ModListPendingChanges.Remove(ChangedMod);
}
catch
{
Logger.Log(Logger.Level.Warn, "OptionsMenu - ModList - Error on Removing Mod to Pending Status Change List");
}
}
else
{
Logger.Log(Logger.Level.Warn, "OptionsMenu - ModList - Error on Adding AND Removing Mod to Pending Status Change List.");
//mhh that should not happen....
}

if (ModListPendingChanges.Count != 0)
{
//enable Apply Button
__instance.applyButton.gameObject.SetActive(true);
}
}
}

[HarmonyPatch(typeof(uGUI_OptionsPanel), nameof(uGUI_OptionsPanel.OnApplyButton))]
internal static class OptionsPatch_OnApplyButton
{
[HarmonyPostfix]
internal static void Postfix(uGUI_OptionsPanel __instance)
{
//Warning Save Button is shared over the hole Option Menu !
if (OptionsManager.ModListPendingChanges.Count > 0)
{
//if the List Contains Pending entries show Info Box
Dialog dialog = new Dialog();
dialog.message = "Important ! Changes on Mods will enforce a Game Reboot after all changes are saved to system.";
dialog.color = Dialog.DialogColor.Red;
dialog.rightButton = Dialog.Button.CancelModChanges;
dialog.leftButton = Dialog.Button.ApplyModChanges;
dialog.Show();
}

//In case User Canceled or the Quit was not executed properly
if (OptionsManager.ModListPendingChanges.Count != 0)
{
//As the Original Methode would be disable the Button anyway. We need to Enable it again.
__instance.applyButton.gameObject.SetActive(true);
}
}
}
}
Expand Down
Loading