Esempio n. 1
0
        private bool CheckDependencies(Dictionary <string, Mod> lookup)
        {
            foreach (var mod in lookup.Values)
            {
                var deps = mod.Info.Dependencies;
                if (deps is null)
                {
                    continue;
                }

                foreach (var dep in deps)
                {
                    // Try finding the installed dependency
                    if (!lookup.TryGetValue(dep.Key, out var resolved))
                    {
                        _logger.LogFatal($"Mod {mod} depends on {dep.Key} @ {dep.Value}, but it is not installed");
                        return(false);
                    }

                    // Check if the installed version satisfies the dependency request
                    if (resolved.Info.Version.CompareByPrecedence(dep.Value) == -1)
                    {
                        _logger.LogFatal($"Mod {mod} depends on {resolved.Info.Name ?? resolved.Info.Guid} @ {dep.Value}, but version {resolved.Info.Version} is installed");
                        return(false);
                    }
                }
            }

            return(true);
        }
Esempio n. 2
0
 public static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
 {
     try
     {
         parentLogger.LogInfo("On Scene Loaded" + scene.name);
         UnityEngine.Debug.Log("Loading Scene: " + scene.name);
         if (scene.name == "UI")
         {
             TextMeshProUGUI betaText = GetUITextByName("BETA");
             if (betaText)
             {
                 betaText.text = "INJECTED BUILD - unstable mods";
             }
         }
         else
         {
             TextMeshProUGUI modListText = GetUITextByName("TextMeshPro Text");
             if (modListText)
             {
                 BepInPlugin bepInPlugin = (BepInPlugin)Attribute.GetCustomAttribute(ModdingUtils.parentPlugin.GetType(), typeof(BepInPlugin));
                 if (modListText.text.EndsWith("</size>"))
                 {
                     modListText.text += "\n\nMods Currently Installed:\n";
                 }
                 modListText.text += "\n" + bepInPlugin.Name + " - " + bepInPlugin.Version;
             }
         }
     }
     catch (Exception ex)
     {
         parentLogger.LogFatal(ex);
     }
 }
Esempio n. 3
0
 public static void Finish()
 {
     try
     {
         PluginCache = GetPluginCache();
         Harmony     = new Harmony("QModManager.QModPluginGenerator");
         Harmony.Patch(
             typeof(TypeLoader).GetMethod(nameof(TypeLoader.FindPluginTypes)).MakeGenericMethod(typeof(PluginInfo)),
             postfix: new HarmonyMethod(typeof(QModPluginGenerator).GetMethod(nameof(TypeLoaderFindPluginTypesPostfix))));
     }
     catch (Exception ex)
     {
         Logger.LogFatal($"An exception occurred while attempting to generate BepInEx PluginInfos: {ex.Message}.");
         Logger.LogFatal($"Beginning stacktrace:");
         Logger.LogFatal(ex.StackTrace);
     }
 }
Esempio n. 4
0
 public static void Initialize()
 {
     try
     {
         ApplyHarmonyPatches();
         InitAssemblyResolver();
         ApplyShims();
     }
     catch (Exception ex)
     {
         Logger.LogFatal($"An exception occurred while attempting to apply Harmony shims: {ex.Message}.");
         Logger.LogFatal($"Beginning stacktrace:");
         Logger.LogFatal(ex.StackTrace);
     }
 }
Esempio n. 5
0
 public static void LogF(object data, [CallerLineNumber] int i = 0, [CallerMemberName] string member = "")
 {
     logger.LogFatal(string.Format(Plugin.modName + " ::{0} :: Line: {1}, Method {2}", data, i, member));
 }
Esempio n. 6
0
        private IEnumerator _HostUnsafe()
        {
            _serverLog.LogDebug("Starting server...");

            var config = _config.Host;

            var binding   = config.Binding;
            var ipv4      = binding.IPv4.Value;
            var ipv6      = binding.IPv6.Value;
            var port      = binding.Port.Value;
            var localhost = new IPEndPoint(ipv4 == IPAddress.Any ? IPAddress.Loopback : ipv4, port);

            IPEndPoint publicEndPoint;
            {
                IPAddress publicAddress;
                {
                    var getter = config.PublicBinding.GetAddress();
                    foreach (object o in getter._Run())
                    {
                        yield return(o);
                    }

                    var result = getter.Result;

                    if (!result.Key)
                    {
                        _serverLog.LogFatal($"Failed to get public IP address to host server with: {result.Value}");
                        yield break;
                    }

                    // Safe to parse, already checked by AddressGetter
                    publicAddress = IPAddress.Parse(result.Value);
                }

                ushort publicPort = config.PublicBinding.Port.Value;
                if (publicPort == 0)
                {
                    publicPort = port;
                }

                publicEndPoint = new IPEndPoint(publicAddress, publicPort);
            }


            float  ups = 1 / Time.fixedDeltaTime;            // 90
            double tps = config.TickRate.Value;

            if (tps <= 0)
            {
                _serverLog.LogFatal("The configurable tick rate must be a positive value.");
                yield break;
            }

            if (tps > ups)
            {
                tps = ups;
                _serverLog.LogWarning($"The configurable tick rate ({tps:.00}) is greater than the local fixed update rate ({ups:.00}). The config will be ignored and the fixed update rate will be used instead; running a tick rate higher than your own fixed update rate has no benefits.");
            }

            double tickDeltaTime = 1 / tps;

            Server = new H3Server(_serverLog, _config.Host, _rng, _messages.Server, _messages.ChannelsCount, _version, tickDeltaTime, publicEndPoint);
            _serverLog.LogInfo($"Now hosting on {publicEndPoint}!");

            ConnectLocal(localhost, Server.Secret, Server.HostKey);
        }
        public void Init()
        {
            DontDestroyOnLoad(this);

            Extensions.UnityInjectorPath = Path.GetFullPath(UnityInjectorLocation.Value);

            if (!Directory.Exists(Extensions.UnityInjectorPath))
            {
                Logger.LogInfo($"No UnityInjector path found in {Extensions.UnityInjectorPath}. Creating one...");
                try
                {
                    Directory.CreateDirectory(Extensions.UnityInjectorPath);
                    Directory.CreateDirectory(Extensions.UserDataPath);
                }
                catch (Exception e)
                {
                    Logger.LogFatal($"Failed to create UnityInjector folder! Error message: {e.Message}");
                }

                Destroy(this);
                return;
            }

            managerObject = new GameObject("UnityInjector");

            Logger.LogInfo("UnityInjector started");

            string currentProcess = Process.GetCurrentProcess().ProcessName;

            var plugins = new List <Type>();

            foreach (string pluginDll in Directory.GetFiles(Extensions.UnityInjectorPath, "*.dll"))
            {
                try
                {
                    var pluginAssembly = Assembly.LoadFile(pluginDll);
                    foreach (var type in pluginAssembly.GetTypes())
                    {
                        if (type.IsAbstract || type.IsInterface || !typeof(PluginBase).IsAssignableFrom(type))
                        {
                            continue;
                        }

                        var filterAttributes =
                            (PluginFilterAttribute[])type.GetCustomAttributes(typeof(PluginFilterAttribute), false);

                        if (filterAttributes.Length == 0 ||
                            filterAttributes.Select(attr => attr.ExeName)
                            .Contains(currentProcess, StringComparer.InvariantCultureIgnoreCase))
                        {
                            plugins.Add(type);

                            var name =
                                type.GetCustomAttributes(typeof(PluginNameAttribute), false).FirstOrDefault() as
                                PluginNameAttribute;

                            var version =
                                type.GetCustomAttributes(typeof(PluginVersionAttribute), false).FirstOrDefault() as
                                PluginVersionAttribute;

                            Logger.LogInfo($"UnityInjector: loaded {name?.Name ?? pluginAssembly.GetName().Name} {version?.Version ?? pluginAssembly.GetName().Version.ToString()}");
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.LogError($"Failed to load {pluginDll}. Stack trace:\n{e}");
                }
            }

            if (plugins.Count == 0)
            {
                Logger.LogInfo("UnityInjector: No plugins found!");
                Destroy(managerObject);
                Destroy(this);
                return;
            }

            foreach (var plugin in plugins)
            {
                try
                {
                    managerObject.AddComponent(plugin);
                }
                catch (Exception e)
                {
                    Logger.LogError($"UnityInjector: Failed to initialize {plugin.Assembly.GetName().Name}\nError: {e}");
                }
            }

            Logger.LogInfo("UnityInjector: All plugins loaded");

            managerObject.SetActive(true);
        }
Esempio n. 8
0
 public static void LogF(object data) => logger.LogFatal(data);
 public static void LogFatal(object log)
 {
     LogSource.LogFatal(log);
 }
Esempio n. 10
0
        public void CleanTranslationCache()
        {
            Logger.LogMessage("Attempting to clean translation cache, please be patient...");
            var cache = GeBoAPI.Instance.AutoTranslationHelper.DefaultCache;

            if (cache == null)
            {
                Logger.LogError("Unable to access translation cache");
                return;
            }

            var translations = GeBoAPI.Instance.AutoTranslationHelper.GetTranslations() ??
                               new Dictionary <string, string>();
            var regexes = new List <Regex>();

            var tmp = GeBoAPI.Instance.AutoTranslationHelper.GetRegisteredRegexes();

            if (tmp != null)
            {
                regexes.AddRange(tmp.Select(s => new Regex(s)));
            }

            tmp = GeBoAPI.Instance.AutoTranslationHelper.GetRegisteredSplitterRegexes();
            if (tmp != null)
            {
                regexes.AddRange(tmp.Select(s => new Regex(s)));
            }

            var newFile = GetWorkFileName(Path.GetDirectoryName(AutoTranslationsFilePath),
                                          Path.GetFileName(AutoTranslationsFilePath), "new");
            var backupFile = GetWorkFileName(Path.GetDirectoryName(AutoTranslationsFilePath),
                                             Path.GetFileName(AutoTranslationsFilePath), "bak");

            MoveReplaceFile(AutoTranslationsFilePath, backupFile);
            Logger.LogInfo("Reloading translations without existing cache file");
            ReloadTranslations();

            var completed = false;

            try
            {
                char[] splitter = { '=' };
                var    changed  = 0;
                using (var outStream = File.Open(newFile, FileMode.CreateNew, FileAccess.Write))
                    using (var writer = new StreamWriter(outStream, Encoding.UTF8))
                        using (var inStream = File.Open(backupFile, FileMode.Open, FileAccess.Read))
                            using (var reader = new StreamReader(inStream, Encoding.UTF8))
                            {
                                string line;
                                while ((line = reader.ReadLine()) != null)
                                {
                                    var parts = line.Split(splitter, StringSplitOptions.None);
                                    if (parts.Length == 2 && !parts[0].StartsWith("//", StringComparison.InvariantCulture))
                                    {
                                        if (translations.ContainsKey(parts[0]))
                                        {
                                            Logger.LogInfo($"Removing cached line (static match): {line.TrimEnd()}");
                                            changed++;
                                            continue;
                                        }

                                        if (regexes.Any(r => r.IsMatch(parts[0])))
                                        {
                                            Logger.LogInfo($"Removing cached line (regex match): {line.TrimEnd()}");
                                            changed++;
                                            continue;
                                        }
                                    }

                                    writer.WriteLine(line);
                                }
                            }

                if (changed > 0)
                {
                    Logger.LogMessage($"Done. Removed {changed} entries from cache. Reloading translations.");
                    MoveReplaceFile(newFile, AutoTranslationsFilePath);
                }
                else
                {
                    Logger.LogMessage("Done. No changes made. Restoring/reloading translations");
                    MoveReplaceFile(backupFile, AutoTranslationsFilePath);
                }

                ReloadTranslations();
                completed = true;
            }
            catch (Exception e)
            {
                Logger.LogFatal(e.Message);
                Logger.LogError(e.StackTrace);
                throw;
            }
            finally
            {
                if (!completed)
                {
                    if (File.Exists(backupFile))
                    {
                        Logger.LogWarning("Something unexpected happened. Restoring previous translation cache.");
                        MoveReplaceFile(backupFile, AutoTranslationsFilePath);
                        ReloadTranslations();
                    }
                }
            }
        }
Esempio n. 11
0
    public static void Start(string[] args)
    {
        var preloaderListener = new PreloaderConsoleListener();

        Logger.Listeners.Add(preloaderListener);

        if (string.IsNullOrEmpty(ConfigEntrypointExecutable.Value))
        {
            Log.Log(LogLevel.Fatal,
                    $"Entry executable was not set. Please set this in your config before launching the application");
            Program.ReadExit();
            return;
        }

        var executablePath = Path.GetFullPath(ConfigEntrypointExecutable.Value);

        if (!File.Exists(executablePath))
        {
            Log.Log(LogLevel.Fatal, $"Unable to locate executable: {ConfigEntrypointExecutable.Value}");
            Program.ReadExit();
            return;
        }


        Paths.SetExecutablePath(executablePath);
        Program.ResolveDirectories.Add(Paths.GameRootPath);

        foreach (var searchDir in Program.ResolveDirectories)
        {
            TypeLoader.SearchDirectories.Add(searchDir);
        }

        if (PlatformHelper.Is(Platform.Windows))
        {
            AddDllDirectory(Paths.GameRootPath);
            SetDllDirectory(Paths.GameRootPath);
        }


        Logger.Sources.Add(TraceLogSource.CreateSource());

        ChainloaderLogHelper.PrintLogInfo(Log);

        Log.Log(LogLevel.Info, $"CLR runtime version: {Environment.Version}");


        AssemblyBuildInfo executableInfo, launcherInfo;

        using (var executableAssembly = AssemblyDefinition.ReadAssembly(executablePath))
            executableInfo = AssemblyBuildInfo.DetermineInfo(executableAssembly);

        using (var launcherAssembly = AssemblyDefinition.ReadAssembly(typeof(NetPreloader).Assembly.Location))
            launcherInfo = AssemblyBuildInfo.DetermineInfo(launcherAssembly);

        // we don't particularly care about AnyCPU here since the fallback bitness is almost never the case
        if (executableInfo.Is64Bit != launcherInfo.Is64Bit)
        {
            Log.LogError($"Game executable is {(executableInfo.Is64Bit ? "64" : "32")}-bit while BepInEx has been compiled as {(launcherInfo.Is64Bit ? "64" : "32")}-bit. Expect crashes");
        }

        if (executableInfo.NetFrameworkVersion != launcherInfo.NetFrameworkVersion || executableInfo.AssemblyFrameworkType != launcherInfo.AssemblyFrameworkType)
        {
            Log.LogWarning($"Game executable has been compiled as {executableInfo}, while BepInEx has been compiled as {launcherInfo}. There may be issues within the game caused by this");
        }

        Log.LogInfo($"Game executable build architecture: {executableInfo}");
        Log.LogInfo($"BepInEx launcher build architecture: {launcherInfo}");

        Log.Log(LogLevel.Message, "Preloader started");

        Assembly entrypointAssembly;

        using (var assemblyPatcher = new AssemblyPatcher())
        {
            assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath);

            Log.Log(LogLevel.Info,
                    $"{assemblyPatcher.PatcherContext.PatchDefinitions.Count} patcher definition(s) loaded");

            assemblyPatcher.LoadAssemblyDirectories(new[] { Paths.GameRootPath }, new[] { "dll", "exe" });

            Log.Log(LogLevel.Info, $"{assemblyPatcher.PatcherContext.AvailableAssemblies.Count} assemblies discovered");

            assemblyPatcher.PatchAndLoad();


            var assemblyName = AssemblyName.GetAssemblyName(executablePath);

            entrypointAssembly =
                assemblyPatcher.PatcherContext.LoadedAssemblies.Values.FirstOrDefault(x => x.FullName ==
                                                                                      assemblyName.FullName);

            foreach (var loadedAssembly in assemblyPatcher.PatcherContext.LoadedAssemblies)
            {
                // TODO: Need full paths for loaded assemblies
                var assemblyPath = Path.Combine(Paths.GameRootPath, loadedAssembly.Key);

                Log.LogDebug($"Registering '{assemblyPath}' as a loaded assembly");
                AssemblyFixes.AssemblyLocations[loadedAssembly.Value.FullName] = assemblyPath;
            }

            if (entrypointAssembly != null)
            {
                Log.LogDebug("Found patched entrypoint assembly! Using it");
            }
            else
            {
                Log.LogDebug("Using entrypoint assembly from disk");
                entrypointAssembly = Assembly.LoadFrom(executablePath);
            }
        }

        Log.LogMessage("Preloader finished");

        Logger.Listeners.Remove(preloaderListener);

        var chainloader = new NetChainloader();

        chainloader.Initialize();
        chainloader.Execute();


        AssemblyFixes.Execute(entrypointAssembly);

        try
        {
            var argList = new List <object>();

            var paramTypes = entrypointAssembly.EntryPoint.GetParameters();

            if (paramTypes.Length == 1 && paramTypes[0].ParameterType == typeof(string[]))
            {
                argList.Add(args);
            }
            else if (paramTypes.Length == 1 && paramTypes[0].ParameterType == typeof(string))
            {
                argList.Add(string.Join(" ", args));
            }
            else if (paramTypes.Length != 0)
            {
                // Only other entrypoint signatures I can think of that .NET supports is Task / Task<int>
                //   async entrypoints. That's a can of worms for another time though

                Log.LogFatal($"Could not figure out how to handle entrypoint method with this signature: {entrypointAssembly.EntryPoint.FullDescription()}");
                return;
            }

            entrypointAssembly.EntryPoint.Invoke(null, argList.ToArray());
        }
        catch (Exception ex)
        {
            Log.LogFatal($"Unhandled exception: {ex}");
        }
    }
Esempio n. 12
0
 public static void LogF(object data, [CallerLineNumber] int i = 0, [CallerMemberName] string member = "")
 {
     logger.LogFatal(string.Format("TrinketsAndBaubles ::{0} :: Line: {1}, Method {2}", data, i, member));
 }
Esempio n. 13
0
 public static void Fatal(object data) => _logSource.LogFatal(data);
Esempio n. 14
0
 public static void LogFatal(object data)
 {
     logger.LogFatal(data);
 }
Esempio n. 15
0
 internal static void LogFatal(object data) => _logSource.LogFatal(data);
Esempio n. 16
0
        public static void Start(string[] args)
        {
            if (ConfigEntrypointExecutable.Value == null)
            {
                Log.LogFatal($"Entry executable was not set. Please set this in your config before launching the application");
                Program.ReadExit();
                return;
            }

            string executablePath = Path.GetFullPath(ConfigEntrypointExecutable.Value);

            if (!File.Exists(executablePath))
            {
                Log.LogFatal($"Unable to locate executable: {ConfigEntrypointExecutable.Value}");
                Program.ReadExit();
                return;
            }

            Paths.SetExecutablePath(executablePath);
            Program.ResolveDirectories.Add(Paths.GameRootPath);
            TypeLoader.SearchDirectories.Add(Paths.GameRootPath);

            Logger.Sources.Add(TraceLogSource.CreateSource());

            ChainloaderLogHelper.PrintLogInfo(Log);

            Log.LogInfo($"CLR runtime version: {Environment.Version}");

            Log.LogMessage("Preloader started");

            Assembly entrypointAssembly;

            using (var assemblyPatcher = new AssemblyPatcher())
            {
                assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath);

                Log.LogInfo($"{assemblyPatcher.PatcherPlugins.Count} patcher plugin(s) loaded");

                assemblyPatcher.LoadAssemblyDirectory(Paths.GameRootPath, "dll", "exe");

                Log.LogInfo($"{assemblyPatcher.AssembliesToPatch.Count} assemblies discovered");

                assemblyPatcher.PatchAndLoad();


                var assemblyName = AssemblyName.GetAssemblyName(executablePath);

                entrypointAssembly = assemblyPatcher.LoadedAssemblies.Values.FirstOrDefault(x => x.FullName == assemblyName.FullName);

                if (entrypointAssembly != null)
                {
                    Log.LogDebug("Found patched entrypoint assembly! Using it");
                }
                else
                {
                    Log.LogDebug("Using entrypoint assembly from disk");
                    entrypointAssembly = Assembly.LoadFrom(executablePath);
                }
            }

            Log.LogMessage("Preloader finished");

            var chainloader = new NetChainloader();

            chainloader.Initialize();
            chainloader.Execute();


            AssemblyFix.Execute(entrypointAssembly);

            entrypointAssembly.EntryPoint.Invoke(null, new [] { args });
        }
Esempio n. 17
0
 public void Critical(string str)
 {
     logSource.LogFatal(str);
 }