Пример #1
0
        private void CompileScripts()
        {
            if (!Directory.Exists(scriptsPath))
            {
                Directory.CreateDirectory(scriptsPath);
                return;
            }

            var files = Directory.GetFiles(scriptsPath, "*.cs");

            availableScripts = files.ToDictionary(f => f, ScriptInfo.FromTextFile);

            var ignoresPath = Path.Combine(scriptsPath, "scriptignores");

            if (!File.Exists(ignoresPath))
            {
                File.WriteAllText(ignoresPath, "");
            }

            var ignores          = new HashSet <string>(File.ReadAllLines(ignoresPath).Select(s => s.Trim()));
            var scriptsToCompile = files.Where(f => !ignores.Contains(Path.GetFileName(f))).ToList();

            Logger.LogInfo(
                $"Found {files.Length} scripts to compile, skipping {files.Length - scriptsToCompile.Count} scripts because of `scriptignores`");

            var md5        = MD5.Create();
            var scriptDict = new Dictionary <string, byte[]>();

            foreach (var scriptFile in scriptsToCompile)
            {
                var data = File.ReadAllBytes(scriptFile);
                md5.TransformBlock(data, 0, data.Length, null, 0);
                scriptDict[scriptFile] = data;
            }

            md5.TransformFinalBlock(new byte[0], 0, 0);
            var hash = Convert.ToBase64String(md5.Hash);

            if (hash == lastCompilationHash)
            {
                Logger.LogInfo("No changes detected! Skipping compilation!");
                return;
            }

            foreach (var scriptFile in scriptsToCompile)
            {
                if (!availableScripts.TryGetValue(scriptFile, out var info) || info == null)
                {
                    continue;
                }
                foreach (var infoReference in info.References)
                {
                    Assembly.LoadFile(infoReference);
                }
            }

            var ass = MonoCompiler.Compile(scriptDict, loggerTextWriter);

            if (ass == null)
            {
                Logger.LogError("Skipping loading scripts because of errors above.");
                return;
            }

            if (lastCompilationAssembly != null)
            {
                foreach (var type in lastCompilationAssembly.GetTypes())
                {
                    var method = type.GetMethods(BindingFlags.Static | BindingFlags.Public)
                                 .FirstOrDefault(m => m.Name == "Unload" && m.GetParameters().Length == 0);

                    if (method == null)
                    {
                        continue;
                    }

                    Logger.Log(LogLevel.Info, $"Unloading {type.Name}");
                    method.Invoke(null, new object[0]);
                }
            }

            lastCompilationAssembly = ass;
            lastCompilationHash     = hash;

            foreach (var type in ass.GetTypes())
            {
                var method = type.GetMethods(BindingFlags.Static | BindingFlags.Public)
                             .FirstOrDefault(m => m.Name == "Main" && m.GetParameters().Length == 0);

                if (method == null)
                {
                    continue;
                }

                Logger.Log(LogLevel.Info, $"Running {type.Name}");
                method.Invoke(null, new object[0]);
            }
        }
Пример #2
0
        private void CompileScripts()
        {
            if (!Directory.Exists(ScriptsPath))
            {
                Directory.CreateDirectory(ScriptsPath);
                return;
            }

            try
            {
                var files = Directory.GetFiles(ScriptsPath, "*.cs");
                AvailableScripts = files.ToDictionary(f => f, ScriptInfo.FromTextFile);

                Logger.Info($"Found {files.Length} scripts to compile");

                var md5        = MD5.Create();
                var scriptDict = new Dictionary <string, byte[]>();
                foreach (var scriptFile in files)
                {
                    var data = File.ReadAllBytes(scriptFile);
                    md5.TransformBlock(data, 0, data.Length, null, 0);
                    scriptDict[scriptFile] = data;
                }

                md5.TransformFinalBlock(new byte[0], 0, 0);
                var hash = Convert.ToBase64String(md5.Hash);

                if (hash == _lastCompilationHash)
                {
                    Logger.Info("No changes detected! Skipping compilation!");
                    return;
                }

                foreach (var scriptFile in files)
                {
                    if (!AvailableScripts.TryGetValue(scriptFile, out var info))
                    {
                        continue;
                    }
                    foreach (var infoReference in info.References)
                    {
                        Assembly.LoadFile(infoReference);
                    }
                }

                var ass = MonoCompiler.Compile(scriptDict, _loggerTextWriter);

                if (ass == null)
                {
                    _lastCompilationHash = null;
                    Logger.Error("Skipping loading scripts because of errors above.");
                    return;
                }

                if (_lastCompilationAssembly != null)
                {
                    foreach (var type in _lastCompilationAssembly.GetTypes())
                    {
                        Api.CommandManager.UnregisterCommand(type);

                        var method = type.GetMethods(BindingFlags.Static | BindingFlags.Public)
                                     .FirstOrDefault(m => m.Name == "Unload" && m.GetParameters().Length == 0);

                        if (method == null)
                        {
                            continue;
                        }

                        SixModLoader.SixModLoader.Instance.EventManager.UnregisterStatic(type);
                        Logger.Info($"Unloading {type.Name}");
                        method.Invoke(null, new object[0]);
                    }
                }

                _lastCompilationAssembly = ass;
                _lastCompilationHash     = hash;

                foreach (var type in ass.GetTypes())
                {
                    Api.CommandManager.RegisterCommand(type);

                    var method = type.GetMethods(BindingFlags.Static | BindingFlags.Public)
                                 .FirstOrDefault(m => m.Name == "Main" && m.GetParameters().Length == 0);

                    if (method == null)
                    {
                        continue;
                    }

                    SixModLoader.SixModLoader.Instance.EventManager.RegisterStatic(type);
                    Logger.Info($"Running {type.Name}");
                    method.Invoke(null, new object[0]);
                }
            }
            catch (Exception e)
            {
                Logger.Error("Failed compiling scripts\n" + e);
            }
        }