Skip to content

Commit

Permalink
Add Welcome Message, Engine Agnostic Launch Options
Browse files Browse the repository at this point in the history
  • Loading branch information
RinLovesYou committed Dec 28, 2023
1 parent 0f99afd commit e179c05
Show file tree
Hide file tree
Showing 15 changed files with 405 additions and 17 deletions.
4 changes: 2 additions & 2 deletions MelonLoader/MelonLoader.Bootstrap/Entrypoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static unsafe void Entry()
MelonDebug.Msg("Starting Up...");
MelonDebug.Msg(MelonEnvironment.MelonLoaderDirectory);

MelonLogger.Msg($"Executable: {MelonEnvironment.GameExecutableName}");
MelonDebug.Msg($"Executable: {MelonEnvironment.GameExecutableName}");

var module = ModuleManager.FindBootstrapModule();
if (module == null)
Expand All @@ -25,7 +25,7 @@ public static unsafe void Entry()
}

MelonDebug.Msg("Found Bootstrap Module: " + module.GetType().FullName);
MelonLogger.Msg($"Running Engine: {module.EngineName}");
MelonDebug.Msg($"Running Engine: {module.EngineName}");

// Fix Resolving Issue
UnhandledAssemblyResolve.AddSearchDirectoryToFront(Path.Combine(MelonEnvironment.ModulesDirectory, module.EngineName, "net6"));
Expand Down
2 changes: 1 addition & 1 deletion MelonLoader/MelonLoader.Shared/BootstrapInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using MelonLoader.Utils;
using System.Runtime.InteropServices;

#if !NET6_0
#if !NET6_0_OR_GREATER
using System.Runtime.CompilerServices;
#endif

Expand Down
50 changes: 43 additions & 7 deletions MelonLoader/MelonLoader.Shared/Core.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
using MelonLoader.Fixes;
using MelonLoader.Utils;
using System;
using System.Runtime.InteropServices;
using System.Text;
using HarmonyLib;
using MelonLoader.Properties;

namespace MelonLoader
{
public class Core
{
internal static Harmony HarmonyInstance;
public static readonly bool IsAlpha = true;
public static void Startup(string engineModulePath)
{
MelonEnvironment.Initialize();
MelonDebug.Msg("MelonLoader.Core.Startup");
OsUtils.SetupWineCheck();

UnhandledException.Install(AppDomain.CurrentDomain);
UnhandledAssemblyResolve.Install();

if (engineModulePath != null)
{
MelonDebug.Msg($"Engine Module Path: {engineModulePath}");
var module = ModuleManager.LoadModule(engineModulePath);
module.Initialize();
}
if (engineModulePath == null)
return;

HarmonyInstance = new Harmony(BuildInfo.Name);

MelonDebug.Msg($"Engine Module Path: {engineModulePath}");
var module = ModuleManager.LoadModule(engineModulePath);
module.Initialize();

MelonUtils.Setup(AppDomain.CurrentDomain);
}

public static void OnApplicationPreStart()
Expand All @@ -32,5 +41,32 @@ public static void OnApplicationStart()
{
MelonDebug.Msg("MelonLoader.Core.OnApplicationStart");
}

private static string GetVersionString()
{
StringBuilder sb = new();
sb.Append("MelonLoader ");
sb.Append($"v{BuildInfo.Version} ");
sb.Append(IsAlpha ? "ALPHA Pre-Release" : "Open-Beta");

return sb.ToString();
}

internal static void WelcomeMessage()
{
MelonLogger.MsgDirect("------------------------------");
MelonLogger.MsgDirect(GetVersionString());
MelonLogger.MsgDirect($"OS: {OsUtils.GetOSVersion()}");
MelonLogger.MsgDirect($"Hash Code: {MelonUtils.HashCode}");
MelonLogger.MsgDirect("------------------------------");
var typeString = ModuleManager.EngineModule.RuntimeName;
MelonLogger.MsgDirect($"Engine: {ModuleManager.EngineModule.EngineName}");
MelonLogger.MsgDirect($"Game Type: {typeString}");
var archString = MelonUtils.IsGame32Bit ? "x86" : "x64";
MelonLogger.MsgDirect($"Game Arch: {archString}");
MelonLogger.MsgDirect("------------------------------");

MelonEnvironment.PrintEnvironment();
}
}
}
1 change: 1 addition & 0 deletions MelonLoader/MelonLoader.Shared/Interfaces/IEngineModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace MelonLoader.Interfaces
public interface IEngineModule
{
string EngineName { get; }
string RuntimeName { get; }

void Initialize();
}
Expand Down
9 changes: 5 additions & 4 deletions MelonLoader/MelonLoader.Shared/ModuleManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@

namespace MelonLoader
{
public static class ModuleManager
internal static class ModuleManager
{
public static IBootstrapModule FindBootstrapModule()
internal static IEngineModule EngineModule { get; private set; }
internal static IBootstrapModule FindBootstrapModule()
{
foreach (var bootstrapPath in Directory.GetFiles(MelonEnvironment.ModulesDirectory, "*.Bootstrap.dll", SearchOption.AllDirectories))
{
Expand Down Expand Up @@ -58,8 +59,8 @@ internal static IEngineModule LoadModule(string modulePath)

try
{
var module = (IEngineModule)Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, null, null);
return module;
EngineModule = (IEngineModule)Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, null, null);
return EngineModule;
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ namespace MelonLoader.NativeUtils
{
public static class MelonNativeLibrary
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStr)]
internal delegate string StringDelegate();

public static bool TryLoad(string name, out IntPtr result)
{
bool wasSuccessful = false;
Expand Down
16 changes: 16 additions & 0 deletions MelonLoader/MelonLoader.Shared/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using MelonLoader.Properties;

[assembly: AssemblyTitle(BuildInfo.Description)]
[assembly: AssemblyDescription(BuildInfo.Description)]
[assembly: AssemblyCompany(BuildInfo.Company)]
[assembly: AssemblyProduct(BuildInfo.Name)]
[assembly: AssemblyCopyright("Created by " + BuildInfo.Author)]
[assembly: AssemblyTrademark(BuildInfo.Company)]
[assembly: Guid("A662769A-B294-434F-83B5-176FC4795334")]
[assembly: AssemblyVersion(BuildInfo.Version)]
[assembly: AssemblyFileVersion(BuildInfo.Version)]

[assembly: InternalsVisibleTo("MelonLoader.Bootstrap")]
10 changes: 10 additions & 0 deletions MelonLoader/MelonLoader.Shared/Properties/BuildInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace MelonLoader.Properties;

public static class BuildInfo
{
public const string Name = "MelonLoader";
public const string Description = "MelonLoader";
public const string Author = "Lava Gang";
public const string Company = "discord.gg/2Wn3N2P";
public const string Version = "1.0.0";
}
4 changes: 4 additions & 0 deletions MelonLoader/MelonLoader.Shared/Utils/MelonDebug.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ public static void Error(string txt)

public static bool IsEnabled()
{
#if DEBUG
return true;
#else
return MelonLaunchOptions.Core.IsDebug;
#endif
}
}
}
17 changes: 17 additions & 0 deletions MelonLoader/MelonLoader.Shared/Utils/MelonEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ namespace MelonLoader.Utils
{
public static class MelonEnvironment
{
private const string OurRuntimeName =
#if NET35_OR_GREATER
"net35";
#elif NETSTANDARD2_1_OR_GREATER
"netstandard2.1";
#else
"net6";
#endif
public static string GameRootDirectory { get; private set; }
public static string GameExecutablePath { get; private set; }
public static string GameExecutableName { get; private set; }
Expand Down Expand Up @@ -42,5 +50,14 @@ internal static void Initialize()
UserLibsDirectory = Path.Combine(MelonBaseDirectory, "UserLibs");
UserDataDirectory = Path.Combine(MelonBaseDirectory, "UserData");
}

internal static void PrintEnvironment()
{
MelonLogger.MsgDirect($"Core::BasePath = {MelonBaseDirectory}");
MelonLogger.MsgDirect($"Game::BasePath = {GameRootDirectory}");
MelonLogger.MsgDirect($"Game::ApplicationPath = {GameExecutablePath}");

MelonLogger.MsgDirect($"Runtime Type: {OurRuntimeName}");
}
}
}
173 changes: 173 additions & 0 deletions MelonLoader/MelonLoader.Shared/Utils/MelonLaunchOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
using System;
using System.Collections.Generic;

namespace MelonLoader.Utils;

public static class MelonLaunchOptions
{
private static Dictionary<string, Action> WithoutArg = new Dictionary<string, Action>();
private static Dictionary<string, Action<string>> WithArg = new Dictionary<string, Action<string>>();

static MelonLaunchOptions()
{
AnalyticsBlocker.Setup();
Core.Setup();
Console.Setup();
Logger.Setup();
}

internal static void Load()
{
var foundOptions = new List<string>();

using var argEnumerator = (IEnumerator<string>)Environment.GetCommandLineArgs().GetEnumerator();
while (argEnumerator.MoveNext())
{
string fullcmd = argEnumerator.Current;
if (string.IsNullOrEmpty(fullcmd))
continue;

if (!fullcmd.StartsWith("--"))
continue;

string cmd = fullcmd.Remove(0, 2);

if (WithoutArg.TryGetValue(cmd, out Action withoutArgFunc))
{
foundOptions.Add(fullcmd);
withoutArgFunc();
}
else if (WithArg.TryGetValue(cmd, out Action<string> withArgFunc))
{
if (!argEnumerator.MoveNext())
continue;

string cmdArg = argEnumerator.Current;
if (string.IsNullOrEmpty(cmdArg))
continue;

if (cmdArg.StartsWith("--"))
continue;

foundOptions.Add($"{fullcmd} = {cmdArg}");
withArgFunc(cmdArg);
}
}

if (foundOptions.Count <= 0)
return;
}

#region Args

public static class AnalyticsBlocker
{
public static bool ShouldDAB { get; internal set; }

internal static void Setup()
{
WithoutArg["melonloader.dab"] = () => ShouldDAB = true;
}
}

public static class Core
{
public enum LoadModeEnum
{
NORMAL,
DEV,
BOTH
}

public static LoadModeEnum LoadMode_Plugins { get; internal set; }
public static LoadModeEnum LoadMode_Mods { get; internal set; }
public static bool QuitFix { get; internal set; }
public static bool StartScreen { get; internal set; } = true;
public static bool IsDebug { get; internal set; }
public static bool UserWantsDebugger { get; internal set; }
public static bool ShouldDisplayAnalyticsBlocker { get; internal set; }

internal static void Setup()
{
WithoutArg["quitfix"] = () => QuitFix = true;
WithoutArg["melonloader.disablestartscreen"] = () => StartScreen = false;
WithArg["melonloader.loadmodeplugins"] = (string arg) =>
{
if (int.TryParse(arg, out int valueint))
LoadMode_Plugins =
(LoadModeEnum)MelonUtils.Clamp(valueint, (int)LoadModeEnum.NORMAL, (int)LoadModeEnum.BOTH);
};
WithArg["melonloader.loadmodemods"] = (string arg) =>
{
if (int.TryParse(arg, out int valueint))
LoadMode_Mods =
(LoadModeEnum)MelonUtils.Clamp(valueint, (int)LoadModeEnum.NORMAL, (int)LoadModeEnum.BOTH);
};
WithoutArg["melonloader.debug"] = () => IsDebug = true;
WithoutArg["melonloader.launchdebugger"] = () => UserWantsDebugger = true;
WithoutArg["melonloader.dab"] = () => ShouldDisplayAnalyticsBlocker = true;
}
}

public static class Console
{
public enum DisplayMode
{
NORMAL,
MAGENTA,
RAINBOW,
RANDOMRAINBOW,
LEMON
};

public static DisplayMode Mode { get; internal set; }
public static bool CleanUnityLogs { get; internal set; } = true;
public static bool ShouldSetTitle { get; internal set; } = true;
public static bool AlwaysOnTop { get; internal set; }
public static bool ShouldHide { get; internal set; }
public static bool HideWarnings { get; internal set; }

internal static void Setup()
{
WithoutArg["melonloader.disableunityclc"] = () => CleanUnityLogs = false;
WithoutArg["melonloader.consoledst"] = () => ShouldSetTitle = false;
WithoutArg["melonloader.consoleontop"] = () => AlwaysOnTop = true;
WithoutArg["melonloader.hideconsole"] = () => ShouldHide = true;
WithoutArg["melonloader.hidewarnings"] = () => HideWarnings = true;

WithArg["melonloader.consolemode"] = (string arg) =>
{
if (int.TryParse(arg, out int valueint))
Mode = (DisplayMode)MelonUtils.Clamp(valueint, (int)DisplayMode.NORMAL, (int)DisplayMode.LEMON);
};
}
}

public static class Logger
{
public static int MaxLogs { get; internal set; } = 10;
public static int MaxWarnings { get; internal set; } = 10;
public static int MaxErrors { get; internal set; } = 10;

internal static void Setup()
{
WithArg["melonloader.maxlogs"] = (string arg) =>
{
if (int.TryParse(arg, out int valueint))
MaxLogs = valueint;
};
WithArg["melonloader.maxwarnings"] = (string arg) =>
{
if (int.TryParse(arg, out int valueint))
MaxWarnings = valueint;
};
WithArg["melonloader.maxerrors"] = (string arg) =>
{
if (int.TryParse(arg, out int valueint))
MaxErrors = valueint;
};
}
}

#endregion
}
Loading

0 comments on commit e179c05

Please sign in to comment.