/// <summary> /// Loads all extensions in the given directory /// </summary> /// <param name="directory"></param> public void LoadAllExtensions(string directory) { var gameFiles = Directory.GetFiles(directory, GameFileSearchPattern); var files = Directory.GetFiles(directory, ExtFileSearchPattern).Concat(gameFiles); foreach (var file in files) { if (file.Contains(".Ext.") && Array.IndexOf(gameFiles, file.Replace(".Ext.", ".Game.")) != -1) { Logger.Write(LogType.Warning, "Found old game extension '{0}'. Please remove it!", Path.GetFileName(file)); continue; } LoadExtension(Path.Combine(directory, file)); } foreach (var ext in extensions.ToArray()) { try { ext.OnModLoad(); } catch (Exception ex) { extensions.Remove(ext); Logger.WriteException(string.Format("Failed OnModLoad extension {0} v{1}", ext.Name, ext.Version), ex); RemoteLogger.Exception(string.Format("Failed OnModLoad extension {0} v{1}", ext.Name, ext.Version), ex); } } }
/// <summary> /// Initalizes the RCON server /// </summary> public void Initalize() { if (!config.Enabled || listener != null || server != null) { return; } if (string.IsNullOrEmpty(config.Password)) { Interface.Oxide.LogWarning("[Rcon] Remote console password is not set, disabling"); return; } try { server = new WebSocketServer(config.Port); server.WaitTime = TimeSpan.FromSeconds(5.0); server.ReuseAddress = true; server.AddWebSocketService($"/{config.Password}", () => listener = new RconListener(this)); server.Start(); Interface.Oxide.LogInfo($"[Rcon] Server started successfully on port {server.Port}"); } catch (Exception ex) { Interface.Oxide.LogException($"[Rcon] Failed to start server on port {server.Port}", ex); RemoteLogger.Exception($"Failed to start RCON server on port {server.Port}", ex); } }
private void watcher_Error(object sender, ErrorEventArgs e) { Interface.Oxide.NextTick(() => { Interface.Oxide.LogError("FSWatcher error: {0}", new object[] { e.GetException() }); RemoteLogger.Exception("FSWatcher error", e.GetException()); }); }
private void LogMessageReceived(string message, string stackTrace, LogType type) { if (type == LogType.Exception) { RemoteLogger.Exception(message, stackTrace); } }
/// <summary> /// Loads all extensions in the given directory /// </summary> /// <param name="directory"></param> public void LoadAllExtensions(string directory) { var coreExtensions = Directory.GetFiles(directory, coreExtSearchPattern); var gameExtensions = Directory.GetFiles(directory, gameExtSearchPattern); var communityExtensions = Directory.GetFiles(directory, communitySearchPattern); var allExtensions = coreExtensions.Concat(gameExtensions).Concat(communityExtensions); foreach (var ext in allExtensions) { if (ext.Contains(".Ext.") && Array.IndexOf(coreExtensions, ext.Replace(".Ext.", ".Core.")) != -1) { Cleanup.Add(ext); continue; } LoadExtension(Path.Combine(directory, ext)); } foreach (var ext in extensions.ToArray()) { try { ext.OnModLoad(); } catch (Exception ex) { extensions.Remove(ext); Logger.WriteException($"Failed OnModLoad extension {ext.Name} v{ext.Version}", ex); RemoteLogger.Exception($"Failed OnModLoad extension {ext.Name} v{ext.Version}", ex); } } }
void LogMessageReceived(string message, string stackTrace, LogType type) { if (type == LogType.Exception && stackTrace.Contains("Oxide")) { RemoteLogger.Exception(message, stackTrace); } }
/// <summary> /// Loads all extensions in the given directory /// </summary> /// <param name="directory"></param> public void LoadAllExtensions(string directory) { var foundExtensions = Directory.GetFiles(directory, extSearchPattern); foreach (var ext in foundExtensions.Where(e => !e.Equals("Oxide.Core.dll"))) { if (ext.Contains(".Core.") && Array.IndexOf(foundExtensions, ext.Replace(".Core.", "")) != -1) { Cleanup.Add(ext); continue; } if (ext.Contains(".Ext.") && Array.IndexOf(foundExtensions, ext.Replace(".Ext.", "")) != -1) { Cleanup.Add(ext); continue; } LoadExtension(Path.Combine(directory, ext)); } foreach (var ext in extensions.ToArray()) { try { ext.OnModLoad(); } catch (Exception ex) { extensions.Remove(ext); Logger.WriteException($"Failed OnModLoad extension {ext.Name} v{ext.Version}", ex); RemoteLogger.Exception($"Failed OnModLoad extension {ext.Name} v{ext.Version}", ex); } } }
public void Initalize() { int?nullable; int?nullable1; int?nullable2; if (!this.config.Enabled || this.listener != null || this.server != null) { return; } if (string.IsNullOrEmpty(this.config.Password)) { Interface.Oxide.LogWarning("[Rcon] Remote console password is not set, disabling", Array.Empty <object>()); return; } try { this.server = new WebSocketServer(this.config.Port) { WaitTime = TimeSpan.FromSeconds(5), ReuseAddress = true }; this.server.AddWebSocketService <Oxide.Core.RemoteConsole.RemoteConsole.RconListener>(string.Concat("/", this.config.Password), () => { Oxide.Core.RemoteConsole.RemoteConsole.RconListener rconListener = new Oxide.Core.RemoteConsole.RemoteConsole.RconListener(this); Oxide.Core.RemoteConsole.RemoteConsole.RconListener rconListener1 = rconListener; this.listener = rconListener; return(rconListener1); }); this.server.Start(); Interface.Oxide.LogInfo(string.Format("[Rcon] Server started successfully on port {0}", this.server.Port), Array.Empty <object>()); } catch (Exception exception1) { Exception exception = exception1; OxideMod oxide = Interface.Oxide; WebSocketServer webSocketServer = this.server; if (webSocketServer != null) { nullable1 = new int?(webSocketServer.Port); } else { nullable = null; nullable1 = nullable; } oxide.LogException(string.Format("[Rcon] Failed to start server on port {0}", nullable1), exception); WebSocketServer webSocketServer1 = this.server; if (webSocketServer1 != null) { nullable2 = new int?(webSocketServer1.Port); } else { nullable = null; nullable2 = nullable; } RemoteLogger.Exception(string.Format("Failed to start RCON server on port {0}", nullable2), exception); } }
internal void Prepare(Action callback) { ThreadPool.QueueUserWorkItem(_ => { try { referencedPlugins.Clear(); references.Clear(); // Include references made by the CSharpPlugins project foreach (var name in CSharpPluginLoader.PluginReferences) { references[name + ".dll"] = new CompilerFile(Interface.Oxide.ExtensionDirectory, name + ".dll"); } CompilablePlugin plugin; while (queuedPlugins.TryDequeue(out plugin)) { if (Current == null) { Current = this; } if (!CacheScriptLines(plugin) || plugin.ScriptLines.Length < 1) { plugin.References.Clear(); plugin.IncludePaths.Clear(); plugin.Requires.Clear(); Interface.Oxide.LogWarning("Plugin script is empty: " + plugin.Name); RemovePlugin(plugin); } else if (plugins.Add(plugin)) { PreparseScript(plugin); ResolveReferences(plugin); } CacheModifiedScripts(); // We don't want the main thread to be able to add more plugins which could be missed if (queuedPlugins.Count == 0 && Current == this) { Current = null; } } //Interface.Oxide.LogDebug("Done preparing compilation: " + plugins.Select(p => p.Name).ToSentence()); callback(); } catch (Exception ex) { Interface.Oxide.LogException("Exception while resolving plugin references", ex); RemoteLogger.Exception("Exception while resolving plugin references", ex); } }); }
/// <summary> /// Loads the extension at the specified filename /// </summary> /// <param name="filename"></param> public void LoadExtension(string filename) { var name = Utility.GetFileNameWithoutExtension(filename); try { // Load the assembly var assembly = Assembly.LoadFile(filename); // Search for a type that derives Extension var extType = typeof(Extension); Type extensionType = null; foreach (var type in assembly.GetExportedTypes()) { if (!extType.IsAssignableFrom(type)) { continue; } extensionType = type; break; } if (extensionType == null) { Logger.Write(LogType.Error, "Failed to load extension {0} ({1})", name, "Specified assembly does not implement an Extension class"); return; } // Create and register the extension var extension = Activator.CreateInstance(extensionType, this) as Extension; if (extension != null) { extension.Load(); extensions.Add(extension); // Log extension loaded Logger.Write(LogType.Info, "Loaded extension {0} v{1} by {2}", extension.Name, extension.Version, extension.Author); } } catch (Exception ex) { Logger.WriteException($"Failed to load extension {name}", ex); RemoteLogger.Exception($"Failed to load extension {name}", ex); } }
private void PatchAssembly(Action <byte[]> callback) { if (isPatching) { Interface.Oxide.LogWarning("Already patching plugin assembly: {0} (ignoring)", PluginNames.ToSentence()); RemoteLogger.Warning($"Already patching plugin assembly: {PluginNames.ToSentence()}"); return; } var startedAt = Interface.Oxide.Now; isPatching = true; ThreadPool.QueueUserWorkItem(_ => { try { AssemblyDefinition definition; using (var stream = new MemoryStream(RawAssembly)) definition = AssemblyDefinition.ReadAssembly(stream); var exceptionConstructor = typeof(UnauthorizedAccessException).GetConstructor(new[] { typeof(string) }); var securityException = definition.MainModule.Import(exceptionConstructor); Action <TypeDefinition> patchModuleType = null; patchModuleType = type => { foreach (var method in type.Methods) { var changedMethod = false; if (method.Body == null) { if (method.HasPInvokeInfo) { method.Attributes &= ~MethodAttributes.PInvokeImpl; var body = new MethodBody(method); body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, "PInvoke access is restricted, you are not allowed to use PInvoke")); body.Instructions.Add(Instruction.Create(OpCodes.Newobj, securityException)); body.Instructions.Add(Instruction.Create(OpCodes.Throw)); method.Body = body; } } else { var replacedMethod = false; foreach (var variable in method.Body.Variables) { if (!IsNamespaceBlacklisted(variable.VariableType.FullName)) { continue; } var body = new MethodBody(method); body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {variable.VariableType.FullName}")); body.Instructions.Add(Instruction.Create(OpCodes.Newobj, securityException)); body.Instructions.Add(Instruction.Create(OpCodes.Throw)); method.Body = body; replacedMethod = true; break; } if (replacedMethod) { continue; } var instructions = method.Body.Instructions; var ilProcessor = method.Body.GetILProcessor(); var first = instructions.First(); var i = 0; while (i < instructions.Count) { if (changedMethod) { break; } var instruction = instructions[i]; if (instruction.OpCode == OpCodes.Ldtoken) { var operand = instruction.Operand as IMetadataTokenProvider; var token = operand?.ToString(); if (IsNamespaceBlacklisted(token)) { ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {token}")); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Newobj, securityException)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Throw)); changedMethod = true; } } else if (instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Calli || instruction.OpCode == OpCodes.Callvirt) { var methodCall = instruction.Operand as MethodReference; var fullNamespace = methodCall?.DeclaringType.FullName; if ((fullNamespace == "System.Type" && methodCall.Name == "GetType") || IsNamespaceBlacklisted(fullNamespace)) { ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {fullNamespace}")); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Newobj, securityException)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Throw)); changedMethod = true; } } else if (instruction.OpCode == OpCodes.Ldfld) { var fieldType = instruction.Operand as FieldReference; var fullNamespace = fieldType?.FieldType.FullName; if (IsNamespaceBlacklisted(fullNamespace)) { ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {fullNamespace}")); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Newobj, securityException)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Throw)); changedMethod = true; } } i++; } } if (changedMethod) { method.Body?.OptimizeMacros(); /*//Interface.Oxide.LogDebug("Updating {0} instruction offsets: {1}", instructions.Count, method.FullName); * int curoffset = 0; * for (var i = 0; i < instructions.Count; i++) * { * var instruction = instructions[i]; * instruction.Previous = (i == 0) ? null : instructions[i - 1]; * instruction.Next = (i == instructions.Count - 1) ? null : instructions[i + 1]; * instruction.Offset = curoffset; * curoffset += instruction.GetSize(); * //Interface.Oxide.LogDebug(" {0}", instruction.ToString()); * }*/ } } foreach (var nestedType in type.NestedTypes) { patchModuleType(nestedType); } }; foreach (var type in definition.MainModule.Types) { patchModuleType(type); if (type.Namespace == "Oxide.Plugins") { if (PluginNames.Contains(type.Name)) { var constructor = type.Methods.FirstOrDefault(m => !m.IsStatic && m.IsConstructor && !m.HasParameters && !m.IsPublic); if (constructor != null) { var plugin = CompilablePlugins.SingleOrDefault(p => p.Name == type.Name); if (plugin != null) { plugin.CompilerErrors = "Primary constructor in main class must be public"; } } else { new DirectCallMethod(definition.MainModule, type); } } else { Interface.Oxide.LogWarning( $"A plugin has polluted the global namespace by defining {type.Name}: {PluginNames.ToSentence()}"); RemoteLogger.Info( $"A plugin has polluted the global namespace by defining {type.Name}: {PluginNames.ToSentence()}"); } } } // TODO: Why is there no error on boot using this? foreach (var type in definition.MainModule.Types) { if (type.Namespace != "Oxide.Plugins" || !PluginNames.Contains(type.Name)) { continue; } foreach (var m in type.Methods.Where(m => !m.IsStatic && !m.HasGenericParameters && !m.ReturnType.IsGenericParameter && !m.IsSetter && !m.IsGetter)) { foreach (var parameter in m.Parameters) { foreach (var attribute in parameter.CustomAttributes) { //Interface.Oxide.LogInfo($"{m.FullName} - {parameter.Name} - {attribute.Constructor.FullName}"); } } } } using (var stream = new MemoryStream()) { definition.Write(stream); PatchedAssembly = stream.ToArray(); } Interface.Oxide.NextTick(() => { isPatching = false; //Interface.Oxide.LogDebug("Patching {0} assembly took {1:0.00} ms", ScriptName, Interface.Oxide.Now - startedAt); callback(PatchedAssembly); }); } catch (Exception ex) { Interface.Oxide.NextTick(() => { isPatching = false; Interface.Oxide.LogException($"Exception while patching: {PluginNames.ToSentence()}", ex); RemoteLogger.Exception($"Exception while patching: {PluginNames.ToSentence()}", ex); callback(null); }); } }); }
/// <summary> /// Loads all extensions in the given directory /// </summary> /// <param name="directory"></param> public void LoadAllExtensions(string directory) { List <string> foundCore = new List <string>(); List <string> foundGame = new List <string>(); List <string> foundOther = new List <string>(); string[] coreExtensions = { "Oxide.CSharp", "Oxide.JavaScript", "Oxide.Lua", "Oxide.MySql", "Oxide.Python", "Oxide.SQLite", "Oxide.Unity" }; string[] gameExtensions = { "Oxide.Blackwake", "Oxide.Blockstorm", "Oxide.FortressCraft", "Oxide.FromTheDepths", "Oxide.GangBeasts", "Oxide.Hurtworld", "Oxide.InterstellarRift", "Oxide.MedievalEngineers", "Oxide.Nomad", "Oxide.PlanetExplorers", "Oxide.ReignOfKings", "Oxide.Rust", "Oxide.RustLegacy", "Oxide.SavageLands", "Oxide.SevenDaysToDie", "Oxide.SpaceEngineers", "Oxide.TheForest", "Oxide.Terraria", "Oxide.Unturned" }; string[] foundExtensions = Directory.GetFiles(directory, extSearchPattern); foreach (string extPath in foundExtensions.Where(e => !e.EndsWith("Oxide.Core.dll") && !e.EndsWith("Oxide.References.dll"))) { if (extPath.Contains("Oxide.Core.") && Array.IndexOf(foundExtensions, extPath.Replace(".Core", "")) != -1) { Cleanup.Add(extPath); continue; } if (extPath.Contains("Oxide.Ext.") && Array.IndexOf(foundExtensions, extPath.Replace(".Ext", "")) != -1) { Cleanup.Add(extPath); continue; } if (extPath.Contains("Oxide.Game.")) { Cleanup.Add(extPath); continue; } if (coreExtensions.Contains(extPath.Basename())) { foundCore.Add(extPath); } else if (gameExtensions.Contains(extPath.Basename())) { foundGame.Add(extPath); } else { foundOther.Add(extPath); } } foreach (string extPath in foundCore) { LoadExtension(Path.Combine(directory, extPath), true); } foreach (string extPath in foundGame) { LoadExtension(Path.Combine(directory, extPath), true); } foreach (string extPath in foundOther) { LoadExtension(Path.Combine(directory, extPath), true); } foreach (Extension ext in extensions.ToArray()) { try { ext.OnModLoad(); } catch (Exception ex) { extensions.Remove(ext); Logger.WriteException($"Failed OnModLoad extension {ext.Name} v{ext.Version}", ex); RemoteLogger.Exception($"Failed OnModLoad extension {ext.Name} v{ext.Version}", ex); } } }
/// <summary> /// Loads the extension at the specified filename /// </summary> /// <param name="filename"></param> /// <param name="forced"></param> public void LoadExtension(string filename, bool forced) { string name = Utility.GetFileNameWithoutExtension(filename); // Check if the extension is already loaded if (extensions.Any(x => x.Filename == filename)) { Logger.Write(LogType.Error, $"Failed to load extension '{name}': extension already loaded."); return; } try { // Read the assembly from file byte[] data = File.ReadAllBytes(filename); // Load the assembly Assembly assembly = Assembly.Load(data); // Search for a type that derives Extension Type extType = typeof(Extension); Type extensionType = null; foreach (Type type in assembly.GetExportedTypes()) { if (!extType.IsAssignableFrom(type)) { continue; } extensionType = type; break; } if (extensionType == null) { Logger.Write(LogType.Error, "Failed to load extension {0} ({1})", name, "Specified assembly does not implement an Extension class"); return; } // Create and register the extension Extension extension = Activator.CreateInstance(extensionType, this) as Extension; if (extension != null) { if (!forced) { if (extension.IsCoreExtension || extension.IsGameExtension) { Logger.Write(LogType.Error, $"Failed to load extension '{name}': you may not hotload Core or Game extensions."); return; } if (!extension.SupportsReloading) { Logger.Write(LogType.Error, $"Failed to load extension '{name}': this extension does not support reloading."); return; } } extension.Filename = filename; extension.Load(); extensions.Add(extension); // Log extension loaded Logger.Write(LogType.Info, "Loaded extension {0} v{1} by {2}", extension.Name, extension.Version, extension.Author); } } catch (Exception ex) { Logger.WriteException($"Failed to load extension {name}", ex); RemoteLogger.Exception($"Failed to load extension {name}", ex); } }
private object OnServerCommand(ConsoleSystem.Arg arg) { if (arg?.cmd == null) { return(null); } try { // Get the args var str = arg.GetString(0); if (string.IsNullOrEmpty(str)) { return(null); } // Check if command is from a player var player = arg.Connection?.player as BasePlayer; if (player == null) { return(null); } // Get the full command var message = str.TrimStart('/'); // Parse it string cmd; string[] args; ParseCommand(message, out cmd, out args); if (cmd == null) { return(null); } // Get the covalence player var iplayer = Covalence.PlayerManager.FindPlayerById(arg.Connection.userid.ToString()); if (iplayer == null) { return(null); } // Is the command blocked? var blockedSpecific = Interface.Call("OnPlayerCommand", arg); var blockedCovalence = Interface.Call("OnUserCommand", iplayer, cmd, args); if (blockedSpecific != null || blockedCovalence != null) { return(true); } // Is it a chat command? if (arg.cmd.FullName != "chat.say") { return(null); } if (str[0] != '/') { return(null); // TODO: Return if no arguments given } // Disable chat commands for non-admins if the server is not set to modded if (!Interface.Oxide.Config.Options.Modded && !player.IsAdmin && !permission.UserHasGroup(player.UserIDString, "admin")) { return(null); } // Is it a covalance command? if (Covalence.CommandSystem.HandleChatMessage(iplayer, str)) { return(true); } // Is it a regular chat command? if (!cmdlib.HandleChatCommand(player, cmd, args)) { iplayer.Reply(lang.GetMessage("UnknownCommand", this, iplayer.Id), cmd); } } catch (NullReferenceException ex) { var sb = new StringBuilder(); try { var str = arg?.GetString(0); var message = str?.Substring(1); string cmd; string[] args; ParseCommand(message, out cmd, out args); sb.AppendLine("NullReferenceError in Oxide.Game.Rust when running OnServerCommand."); sb.AppendLine($" Command: {arg.cmd?.FullName}"); sb.AppendLine($" Full command: {str}"); sb.AppendLine($" Command: {cmd}"); sb.AppendLine($" Arguments: {args.ToSentence()}"); sb.AppendLine($" Connection: {arg.Connection}"); sb.AppendLine($" Connection ID: {arg.Connection?.userid}"); sb.AppendLine($" Connection player? {arg.Connection?.player != null}"); sb.AppendLine($" Connection player: {arg.Connection?.player}"); sb.AppendLine($" Connection player type: {arg.Connection?.player?.GetType()}"); } catch { // Ignored } finally { RemoteLogger.Exception(ex.Message, sb.ToString()); } } // Handled arg.ReplyWith(string.Empty); return(true); }
public void LoadAllExtensions(string directory) { List <string> strs = new List <string>(); List <string> strs1 = new List <string>(); List <string> strs2 = new List <string>(); string[] strArrays = new string[] { "Oxide.CSharp", "Oxide.JavaScript", "Oxide.Lua", "Oxide.MySql", "Oxide.Python", "Oxide.SQLite", "Oxide.Unity" }; string[] strArrays1 = new string[] { "Oxide.Blackwake", "Oxide.Blockstorm", "Oxide.FortressCraft", "Oxide.FromTheDepths", "Oxide.GangBeasts", "Oxide.Hurtworld", "Oxide.InterstellarRift", "Oxide.MedievalEngineers", "Oxide.Nomad", "Oxide.PlanetExplorers", "Oxide.ReignOfKings", "Oxide.Rust", "Oxide.RustLegacy", "Oxide.SavageLands", "Oxide.SevenDaysToDie", "Oxide.SpaceEngineers", "Oxide.TheForest", "Oxide.Terraria", "Oxide.Unturned" }; string[] files = Directory.GetFiles(directory, "Oxide.*.dll"); foreach (string str in files.Where <string>((string e) => { if (e.EndsWith("Oxide.Core.dll")) { return(false); } return(!e.EndsWith("Oxide.References.dll")); })) { if (str.Contains("Oxide.Core.") && Array.IndexOf <string>(files, str.Replace(".Core", "")) != -1) { Cleanup.Add(str); } else if (str.Contains("Oxide.Ext.") && Array.IndexOf <string>(files, str.Replace(".Ext", "")) != -1) { Cleanup.Add(str); } else if (str.Contains("Oxide.Game.")) { Cleanup.Add(str); } else if (strArrays.Contains <string>(str.Basename(null))) { strs.Add(str); } else if (!strArrays1.Contains <string>(str.Basename(null))) { strs2.Add(str); } else { strs1.Add(str); } } foreach (string str1 in strs) { this.LoadExtension(Path.Combine(directory, str1), true); } foreach (string str2 in strs1) { this.LoadExtension(Path.Combine(directory, str2), true); } foreach (string str3 in strs2) { this.LoadExtension(Path.Combine(directory, str3), true); } Extension[] array = this.extensions.ToArray <Extension>(); for (int i = 0; i < (int)array.Length; i++) { Extension extension = array[i]; try { extension.OnModLoad(); } catch (Exception exception1) { Exception exception = exception1; this.extensions.Remove(extension); this.Logger.WriteException(string.Format("Failed OnModLoad extension {0} v{1}", extension.Name, extension.Version), exception); RemoteLogger.Exception(string.Format("Failed OnModLoad extension {0} v{1}", extension.Name, extension.Version), exception); } } }
public void LoadExtension(string filename, bool forced) { string fileNameWithoutExtension = Utility.GetFileNameWithoutExtension(filename); if (this.extensions.Any <Extension>((Extension x) => x.Filename == filename)) { this.Logger.Write(LogType.Error, string.Concat("Failed to load extension '", fileNameWithoutExtension, "': extension already loaded."), Array.Empty <object>()); return; } try { Assembly assembly = Assembly.Load(File.ReadAllBytes(filename)); Type type = typeof(Extension); Type type1 = null; Type[] exportedTypes = assembly.GetExportedTypes(); int num = 0; while (num < (int)exportedTypes.Length) { Type type2 = exportedTypes[num]; if (!type.IsAssignableFrom(type2)) { num++; } else { type1 = type2; break; } } if (type1 != null) { Extension extension = Activator.CreateInstance(type1, new object[] { this }) as Extension; if (extension != null) { if (!forced) { if (extension.IsCoreExtension || extension.IsGameExtension) { this.Logger.Write(LogType.Error, string.Concat("Failed to load extension '", fileNameWithoutExtension, "': you may not hotload Core or Game extensions."), Array.Empty <object>()); return; } else if (!extension.SupportsReloading) { this.Logger.Write(LogType.Error, string.Concat("Failed to load extension '", fileNameWithoutExtension, "': this extension does not support reloading."), Array.Empty <object>()); return; } } extension.Filename = filename; extension.Load(); this.extensions.Add(extension); this.Logger.Write(LogType.Info, "Loaded extension {0} v{1} by {2}", new object[] { extension.Name, extension.Version, extension.Author }); } } else { this.Logger.Write(LogType.Error, "Failed to load extension {0} ({1})", new object[] { fileNameWithoutExtension, "Specified assembly does not implement an Extension class" }); } } catch (Exception exception1) { Exception exception = exception1; this.Logger.WriteException(string.Concat("Failed to load extension ", fileNameWithoutExtension), exception); RemoteLogger.Exception(string.Concat("Failed to load extension ", fileNameWithoutExtension), exception); } }