diff --git a/.gitignore b/.gitignore
index 222f5cc..2e77efc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,3 +63,8 @@ _ReSharper*/
*.DotSettings.user
## TeamCity add-in
_TeamCity*
+
+# Other files
+.deploy
+
+src/Debug.cs
diff --git a/LICENSE.md b/LICENSE
similarity index 95%
rename from LICENSE.md
rename to LICENSE
index 02de197..4950b60 100644
--- a/LICENSE.md
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2014-2018 Oxide Team and Contributors
+Copyright (c) 2013-2020 Oxide and Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Oxide.CSharp.sln b/Oxide.CSharp.sln
index ee887e3..eef57a2 100644
--- a/Oxide.CSharp.sln
+++ b/Oxide.CSharp.sln
@@ -1,8 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27004.2008
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29613.14
MinimumVisualStudioVersion = 15.0
-Project("{73BB4989-CA7F-4148-8687-18760A25BC5E}") = "Oxide.CSharp", "src\Oxide.CSharp.csproj", "{9103D682-D1AA-4A95-A499-896F551AAA62}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Oxide.CSharp", "src\Oxide.CSharp.csproj", "{9103D682-D1AA-4A95-A499-896F551AAA62}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,4 +15,10 @@ Global
{9103D682-D1AA-4A95-A499-896F551AAA62}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9103D682-D1AA-4A95-A499-896F551AAA62}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {9C9C46E6-F364-4D0B-8A9E-184ACD86D0BB}
+ EndGlobalSection
EndGlobal
diff --git a/netfx.props b/netfx.props
new file mode 100644
index 0000000..f744186
--- /dev/null
+++ b/netfx.props
@@ -0,0 +1,31 @@
+
+
+
+ True
+
+
+ /Library/Frameworks/Mono.framework/Versions/Current/lib/mono
+ /usr/lib/mono
+ /usr/local/lib/mono
+
+
+ $(BaseFrameworkPathOverrideForMono)/2.0-api
+ $(BaseFrameworkPathOverrideForMono)/4.0-api
+ $(BaseFrameworkPathOverrideForMono)/4.5-api
+ $(BaseFrameworkPathOverrideForMono)/4.5.1-api
+ $(BaseFrameworkPathOverrideForMono)/4.5.2-api
+ $(BaseFrameworkPathOverrideForMono)/4.6-api
+ $(BaseFrameworkPathOverrideForMono)/4.6.1-api
+ $(BaseFrameworkPathOverrideForMono)/4.6.2-api
+ $(BaseFrameworkPathOverrideForMono)/4.7-api
+ $(BaseFrameworkPathOverrideForMono)/4.7.1-api
+ True
+
+
+ C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client
+ /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/2.0-api
+
+
+ $(FrameworkPathOverride)/Facades;$(AssemblySearchPaths)
+
+
diff --git a/nuget.config b/nuget.config
index 63e3798..9098939 100644
--- a/nuget.config
+++ b/nuget.config
@@ -12,6 +12,5 @@
-
diff --git a/resources/icon.png b/resources/icon.png
new file mode 100644
index 0000000..f64c700
Binary files /dev/null and b/resources/icon.png differ
diff --git a/src/CSharpExtension.cs b/src/CSharpExtension.cs
index b757cba..86cfe1f 100644
--- a/src/CSharpExtension.cs
+++ b/src/CSharpExtension.cs
@@ -78,9 +78,12 @@ public CSharpExtension(ExtensionManager manager) : base(manager)
Cleanup.Add(oldCompiler);
}
- var extDir = Interface.Oxide.ExtensionDirectory;
- var configPath = Path.Combine(extDir, "Oxide.References.dll.config");
- if (File.Exists(configPath) && !(new[] { "target=\"x64", "target=\"./x64" }.Any(File.ReadAllText(configPath).Contains))) return;
+ string extDir = Interface.Oxide.ExtensionDirectory;
+ string configPath = Path.Combine(extDir, "Oxide.References.dll.config");
+ if (File.Exists(configPath) && !(new[] { "target=\"x64", "target=\"./x64" }.Any(File.ReadAllText(configPath).Contains)))
+ {
+ return;
+ }
File.WriteAllText(configPath, $"\n\n" +
$"\n");
@@ -140,11 +143,14 @@ public override void OnShutdown()
///
private void OnFrame(float delta)
{
- var args = new object[] { delta };
- foreach (var kv in loader.LoadedPlugins)
+ object[] args = new object[] { delta };
+ foreach (System.Collections.Generic.KeyValuePair kv in loader.LoadedPlugins)
{
- var plugin = kv.Value as CSharpPlugin;
- if (plugin != null && plugin.HookedOnFrame) plugin.CallHook("OnFrame", args);
+ CSharpPlugin plugin = kv.Value as CSharpPlugin;
+ if (plugin != null && plugin.HookedOnFrame)
+ {
+ plugin.CallHook("OnFrame", args);
+ }
}
}
}
diff --git a/src/CSharpPlugin.cs b/src/CSharpPlugin.cs
index cb2132b..fe6293b 100644
--- a/src/CSharpPlugin.cs
+++ b/src/CSharpPlugin.cs
@@ -45,14 +45,25 @@ public InfoAttribute(string Title, string Author, double Version)
private void SetVersion(string version)
{
- var versionParts = version.Split('.').Select(part =>
+ List versionParts = version.Split('.').Select(part =>
{
- ushort number;
- if (!ushort.TryParse(part, out number)) number = 0;
+ if (!ushort.TryParse(part, out ushort number))
+ {
+ number = 0;
+ }
return number;
}).ToList();
- while (versionParts.Count < 3) versionParts.Add(0);
- if (versionParts.Count > 3) Interface.Oxide.LogWarning($"Version `{version}` is invalid for {Title}, should be `major.minor.patch`");
+
+ while (versionParts.Count < 3)
+ {
+ versionParts.Add(0);
+ }
+
+ if (versionParts.Count > 3)
+ {
+ Interface.Oxide.LogWarning($"Version `{version}` is invalid for {Title}, should be `major.minor.patch`");
+ }
+
Version = new VersionNumber(versionParts[0], versionParts[1], versionParts[2]);
}
}
@@ -151,7 +162,7 @@ public PluginFieldInfo(Plugin plugin, FieldInfo field)
public bool HasValidConstructor(params Type[] argument_types)
{
- var type = GenericArguments[1];
+ Type type = GenericArguments[1];
return type.GetConstructor(new Type[0]) != null || type.GetConstructor(argument_types) != null;
}
@@ -159,21 +170,28 @@ public bool HasValidConstructor(params Type[] argument_types)
public bool LookupMethod(string method_name, params Type[] argument_types)
{
- var method = FieldType.GetMethod(method_name, argument_types);
- if (method == null) return false;
+ MethodInfo method = FieldType.GetMethod(method_name, argument_types);
+ if (method == null)
+ {
+ return false;
+ }
+
Methods[method_name] = method;
return true;
}
public object Call(string method_name, params object[] args)
{
- MethodInfo method;
- if (!Methods.TryGetValue(method_name, out method))
+ if (!Methods.TryGetValue(method_name, out MethodInfo method))
{
method = FieldType.GetMethod(method_name, BindingFlags.Instance | BindingFlags.Public);
Methods[method_name] = method;
}
- if (method == null) throw new MissingMethodException(FieldType.Name, method_name);
+ if (method == null)
+ {
+ throw new MissingMethodException(FieldType.Name, method_name);
+ }
+
return method.Invoke(Value, args);
}
}
@@ -201,24 +219,33 @@ public CSharpPlugin()
{
timer = new PluginTimers(this);
- var type = GetType();
- foreach (var field in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
+ Type type = GetType();
+ foreach (FieldInfo field in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
{
- var reference_attributes = field.GetCustomAttributes(typeof(PluginReferenceAttribute), true);
+ object[] reference_attributes = field.GetCustomAttributes(typeof(PluginReferenceAttribute), true);
if (reference_attributes.Length > 0)
{
- var pluginReference = reference_attributes[0] as PluginReferenceAttribute;
+ PluginReferenceAttribute pluginReference = reference_attributes[0] as PluginReferenceAttribute;
pluginReferenceFields[pluginReference.Name ?? field.Name] = field;
}
}
- foreach (var method in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
+ foreach (MethodInfo method in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
{
- var info_attributes = method.GetCustomAttributes(typeof(HookMethodAttribute), true);
- if (info_attributes.Length > 0) continue;
+ object[] info_attributes = method.GetCustomAttributes(typeof(HookMethodAttribute), true);
+ if (info_attributes.Length > 0)
+ {
+ continue;
+ }
- if (method.Name.Equals("OnFrame")) HookedOnFrame = true;
+ if (method.Name.Equals("OnFrame"))
+ {
+ HookedOnFrame = true;
+ }
// Assume all private instance methods which are not explicitly hooked could be hooks
- if (method.DeclaringType.Name == type.Name) AddHookMethod(method.Name, method);
+ if (method.DeclaringType.Name == type.Name)
+ {
+ AddHookMethod(method.Name, method);
+ }
}
}
@@ -227,10 +254,10 @@ public virtual bool SetPluginInfo(string name, string path)
Name = name;
Filename = path;
- var infoAttributes = GetType().GetCustomAttributes(typeof(InfoAttribute), true);
+ object[] infoAttributes = GetType().GetCustomAttributes(typeof(InfoAttribute), true);
if (infoAttributes.Length > 0)
{
- var info = infoAttributes[0] as InfoAttribute;
+ InfoAttribute info = infoAttributes[0] as InfoAttribute;
Title = info.Title;
Author = info.Author;
Version = info.Version;
@@ -242,17 +269,17 @@ public virtual bool SetPluginInfo(string name, string path)
return false;
}
- var descriptionAttributes = GetType().GetCustomAttributes(typeof(DescriptionAttribute), true);
+ object[] descriptionAttributes = GetType().GetCustomAttributes(typeof(DescriptionAttribute), true);
if (descriptionAttributes.Length > 0)
{
- var info = descriptionAttributes[0] as DescriptionAttribute;
+ DescriptionAttribute info = descriptionAttributes[0] as DescriptionAttribute;
Description = info.Description;
}
- var config = GetType().GetMethod("LoadDefaultConfig", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ MethodInfo config = GetType().GetMethod("LoadDefaultConfig", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
HasConfig = config.DeclaringType != typeof(Plugin);
- var messages = GetType().GetMethod("LoadDefaultMessages", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ MethodInfo messages = GetType().GetMethod("LoadDefaultMessages", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
HasMessages = messages.DeclaringType != typeof(Plugin);
return true;
@@ -262,9 +289,15 @@ public override void HandleAddedToManager(PluginManager manager)
{
base.HandleAddedToManager(manager);
- if (Filename != null) Watcher.AddMapping(Name);
+ if (Filename != null)
+ {
+ Watcher.AddMapping(Name);
+ }
- foreach (var name in pluginReferenceFields.Keys) pluginReferenceFields[name].SetValue(this, manager.GetPlugin(name));
+ foreach (string name in pluginReferenceFields.Keys)
+ {
+ pluginReferenceFields[name].SetValue(this, manager.GetPlugin(name));
+ }
/*var compilable_plugin = CSharpPluginLoader.GetCompilablePlugin(Interface.Oxide.PluginDirectory, Name);
if (compilable_plugin != null && compilable_plugin.CompiledAssembly != null)
@@ -286,11 +319,17 @@ public override void HandleAddedToManager(PluginManager manager)
public override void HandleRemovedFromManager(PluginManager manager)
{
- if (IsLoaded) CallHook("Unload", null);
+ if (IsLoaded)
+ {
+ CallHook("Unload", null);
+ }
Watcher.RemoveMapping(Name);
- foreach (var name in pluginReferenceFields.Keys) pluginReferenceFields[name].SetValue(this, null);
+ foreach (string name in pluginReferenceFields.Keys)
+ {
+ pluginReferenceFields[name].SetValue(this, null);
+ }
base.HandleRemovedFromManager(manager);
}
@@ -308,28 +347,41 @@ protected override object InvokeMethod(HookMethod method, object[] args)
{
if (args != null && args.Length > 0)
{
- var parameters = method.Parameters;
- for (var i = 0; i < args.Length; i++)
+ ParameterInfo[] parameters = method.Parameters;
+ for (int i = 0; i < args.Length; i++)
{
- var value = args[i];
- if (value == null) continue;
- var parameter_type = parameters[i].ParameterType;
- if (!parameter_type.IsValueType) continue;
- var argument_type = value.GetType();
+ object value = args[i];
+ if (value == null)
+ {
+ continue;
+ }
+
+ Type parameter_type = parameters[i].ParameterType;
+ if (!parameter_type.IsValueType)
+ {
+ continue;
+ }
+
+ Type argument_type = value.GetType();
if (parameter_type != typeof(object) && argument_type != parameter_type)
+ {
args[i] = Convert.ChangeType(value, parameter_type);
+ }
}
}
try
{
- object ret;
- if (DirectCallHook(method.Name, out ret, args)) return ret;
+ if (DirectCallHook(method.Name, out object ret, args))
+ {
+ return ret;
+ }
+
PrintWarning("Unable to call hook directly: " + method.Name);
}
catch (InvalidProgramException ex)
{
Interface.Oxide.LogError("Hook dispatch failure detected, falling back to reflection based dispatch. " + ex);
- var compilablePlugin = CSharpPluginLoader.GetCompilablePlugin(Interface.Oxide.PluginDirectory, Name);
+ CompilablePlugin compilablePlugin = CSharpPluginLoader.GetCompilablePlugin(Interface.Oxide.PluginDirectory, Name);
if (compilablePlugin?.CompiledAssembly != null)
{
File.WriteAllBytes(Interface.Oxide.PluginDirectory + "\\" + Name + ".dump", compilablePlugin.CompiledAssembly.PatchedAssembly);
@@ -354,15 +406,19 @@ public void SetFailState(string reason)
[HookMethod("OnPluginLoaded")]
private void base_OnPluginLoaded(Plugin plugin)
{
- FieldInfo field;
- if (pluginReferenceFields.TryGetValue(plugin.Name, out field)) field.SetValue(this, plugin);
+ if (pluginReferenceFields.TryGetValue(plugin.Name, out FieldInfo field))
+ {
+ field.SetValue(this, plugin);
+ }
}
[HookMethod("OnPluginUnloaded")]
private void base_OnPluginUnloaded(Plugin plugin)
{
- FieldInfo field;
- if (pluginReferenceFields.TryGetValue(plugin.Name, out field)) field.SetValue(this, null);
+ if (pluginReferenceFields.TryGetValue(plugin.Name, out FieldInfo field))
+ {
+ field.SetValue(this, null);
+ }
}
///
@@ -404,10 +460,17 @@ protected void PrintError(string format, params object[] args)
///
protected void LogToFile(string filename, string text, Plugin plugin, bool timeStamp = true)
{
- var path = Path.Combine(Interface.Oxide.LogDirectory, plugin.Name);
- if (!Directory.Exists(path)) Directory.CreateDirectory(path);
+ string path = Path.Combine(Interface.Oxide.LogDirectory, plugin.Name);
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+
filename = $"{plugin.Name.ToLower()}_{filename.ToLower()}{(timeStamp ? $"-{DateTime.Now:yyyy-MM-dd}" : "")}.txt";
- using (var writer = new StreamWriter(Path.Combine(path, Utility.CleanPath(filename)), true)) writer.WriteLine(text);
+ using (StreamWriter writer = new StreamWriter(Path.Combine(path, Utility.CleanPath(filename)), true))
+ {
+ writer.WriteLine(text);
+ }
}
///
diff --git a/src/CSharpPluginLoader.cs b/src/CSharpPluginLoader.cs
index 0ff4b63..7c469e7 100644
--- a/src/CSharpPluginLoader.cs
+++ b/src/CSharpPluginLoader.cs
@@ -19,9 +19,8 @@ public class CSharpPluginLoader : PluginLoader
public static CompilablePlugin GetCompilablePlugin(string directory, string name)
{
- var className = Regex.Replace(name, "_", "");
- CompilablePlugin plugin;
- if (!plugins.TryGetValue(className, out plugin))
+ string className = Regex.Replace(name, "_", "");
+ if (!plugins.TryGetValue(className, out CompilablePlugin plugin))
{
plugin = new CompilablePlugin(extension, Instance, directory, name);
plugins[className] = plugin;
@@ -45,27 +44,44 @@ public CSharpPluginLoader(CSharpExtension extension)
public void OnModLoaded()
{
// Include references to all loaded game extensions and any assemblies they reference
- foreach (var extension in Interface.Oxide.GetAllExtensions())
+ foreach (Core.Extensions.Extension extension in Interface.Oxide.GetAllExtensions())
{
- if (extension == null || !extension.IsCoreExtension && !extension.IsGameExtension) continue;
+ if (extension == null || !extension.IsCoreExtension && !extension.IsGameExtension)
+ {
+ continue;
+ }
- var assembly = extension.GetType().Assembly;
- var assemblyName = assembly.GetName().Name;
+ System.Reflection.Assembly assembly = extension.GetType().Assembly;
+ string assemblyName = assembly.GetName().Name;
- if (AssemblyBlacklist.Contains(assemblyName)) continue;
+ if (AssemblyBlacklist.Contains(assemblyName))
+ {
+ continue;
+ }
PluginReferences.Add(assemblyName);
- foreach (var reference in assembly.GetReferencedAssemblies())
- if (reference != null) PluginReferences.Add(reference.Name);
+ foreach (System.Reflection.AssemblyName reference in assembly.GetReferencedAssemblies())
+ {
+ if (reference != null)
+ {
+ PluginReferences.Add(reference.Name);
+ }
+ }
}
}
public override IEnumerable ScanDirectory(string directory)
{
- if (PluginCompiler.BinaryPath == null) yield break;
+ if (PluginCompiler.BinaryPath == null)
+ {
+ yield break;
+ }
- var enumerable = base.ScanDirectory(directory);
- foreach (var file in enumerable) yield return file;
+ IEnumerable enumerable = base.ScanDirectory(directory);
+ foreach (string file in enumerable)
+ {
+ yield return file;
+ }
}
///
@@ -76,7 +92,7 @@ public override IEnumerable ScanDirectory(string directory)
///
public override Plugin Load(string directory, string name)
{
- var compilablePlugin = GetCompilablePlugin(directory, name);
+ CompilablePlugin compilablePlugin = GetCompilablePlugin(directory, name);
if (compilablePlugin.IsLoading)
{
Interface.Oxide.LogDebug($"Load requested for plugin which is already loading: {compilablePlugin.Name}");
@@ -99,9 +115,13 @@ public override void Reload(string directory, string name)
if (Regex.Match(directory, @"\\include\b", RegexOptions.IgnoreCase).Success)
{
name = $"Oxide.{name}";
- foreach (var plugin in plugins.Values)
+ foreach (CompilablePlugin plugin in plugins.Values)
{
- if (!plugin.References.Contains(name)) continue;
+ if (!plugin.References.Contains(name))
+ {
+ continue;
+ }
+
Interface.Oxide.LogInfo($"Reloading {plugin.Name} because it references updated include file: {name}");
plugin.LastModifiedAt = DateTime.Now;
Load(plugin);
@@ -109,7 +129,7 @@ public override void Reload(string directory, string name)
return;
}
- var compilablePlugin = GetCompilablePlugin(directory, name);
+ CompilablePlugin compilablePlugin = GetCompilablePlugin(directory, name);
if (compilablePlugin.IsLoading)
{
Interface.Oxide.LogDebug($"Reload requested for plugin which is already loading: {compilablePlugin.Name}");
@@ -126,14 +146,22 @@ public override void Reload(string directory, string name)
///
public override void Unloading(Plugin pluginBase)
{
- var plugin = pluginBase as CSharpPlugin;
- if (plugin == null) return;
+ CSharpPlugin plugin = pluginBase as CSharpPlugin;
+ if (plugin == null)
+ {
+ return;
+ }
LoadedPlugins.Remove(plugin.Name);
// Unload plugins which require this plugin first
- foreach (var compilablePlugin in plugins.Values)
- if (compilablePlugin.Requires.Contains(plugin.Name)) Interface.Oxide.UnloadPlugin(compilablePlugin.Name);
+ foreach (CompilablePlugin compilablePlugin in plugins.Values)
+ {
+ if (compilablePlugin.Requires.Contains(plugin.Name))
+ {
+ Interface.Oxide.UnloadPlugin(compilablePlugin.Name);
+ }
+ }
}
public void Load(CompilablePlugin plugin)
@@ -146,13 +174,16 @@ public void Load(CompilablePlugin plugin)
return;
}
- var loadedLoadingRequirements = plugin.Requires.Where(r => LoadedPlugins.ContainsKey(r) && LoadingPlugins.Contains(r));
- foreach (var loadedPlugin in loadedLoadingRequirements) Interface.Oxide.UnloadPlugin(loadedPlugin);
+ IEnumerable loadedLoadingRequirements = plugin.Requires.Where(r => LoadedPlugins.ContainsKey(r) && LoadingPlugins.Contains(r));
+ foreach (string loadedPlugin in loadedLoadingRequirements)
+ {
+ Interface.Oxide.UnloadPlugin(loadedPlugin);
+ }
- var missingRequirements = plugin.Requires.Where(r => !LoadedPlugins.ContainsKey(r));
+ IEnumerable missingRequirements = plugin.Requires.Where(r => !LoadedPlugins.ContainsKey(r));
if (missingRequirements.Any())
{
- var loadingRequirements = plugin.Requires.Where(r => LoadingPlugins.Contains(r));
+ IEnumerable loadingRequirements = plugin.Requires.Where(r => LoadingPlugins.Contains(r));
if (loadingRequirements.Any())
{
Interface.Oxide.LogDebug($"{plugin.Name} plugin is waiting for requirements to be loaded: {loadingRequirements.ToSentence()}");
@@ -169,7 +200,11 @@ public void Load(CompilablePlugin plugin)
Interface.Oxide.UnloadPlugin(plugin.Name);
plugin.LoadPlugin(pl =>
{
- if (pl != null) LoadedPlugins[pl.Name] = pl;
+ if (pl != null)
+ {
+ LoadedPlugins[pl.Name] = pl;
+ }
+
PluginLoadingCompleted(plugin);
});
}
@@ -210,11 +245,13 @@ private void PluginLoadingCompleted(CompilablePlugin plugin)
{
LoadingPlugins.Remove(plugin.Name);
plugin.IsLoading = false;
- foreach (var loadingName in LoadingPlugins.ToArray())
+ foreach (string loadingName in LoadingPlugins.ToArray())
{
- var loadingPlugin = GetCompilablePlugin(plugin.Directory, loadingName);
+ CompilablePlugin loadingPlugin = GetCompilablePlugin(plugin.Directory, loadingName);
if (loadingPlugin.IsLoading && loadingPlugin.Requires.Contains(plugin.Name))
+ {
Load(loadingPlugin);
+ }
}
}
@@ -224,7 +261,7 @@ private void CompileAssembly(CompilablePlugin[] plugins)
{
if (compilation.compiledAssembly == null)
{
- foreach (var plugin in compilation.plugins)
+ foreach (CompilablePlugin plugin in compilation.plugins)
{
plugin.OnCompilationFailed();
PluginErrors[plugin.Name] = $"Failed to compile: {plugin.CompilerErrors}";
@@ -236,12 +273,12 @@ private void CompileAssembly(CompilablePlugin[] plugins)
{
if (compilation.plugins.Count > 0)
{
- var compiledNames = compilation.plugins.Where(pl => string.IsNullOrEmpty(pl.CompilerErrors)).Select(pl => pl.Name).ToArray();
- var verb = compiledNames.Length > 1 ? "were" : "was";
+ string[] compiledNames = compilation.plugins.Where(pl => string.IsNullOrEmpty(pl.CompilerErrors)).Select(pl => pl.Name).ToArray();
+ string verb = compiledNames.Length > 1 ? "were" : "was";
Interface.Oxide.LogInfo($"{compiledNames.ToSentence()} {verb} compiled successfully in {Math.Round(compilation.duration * 1000f)}ms");
}
- foreach (var plugin in compilation.plugins)
+ foreach (CompilablePlugin plugin in compilation.plugins)
{
if (plugin.CompilerErrors == null)
{
diff --git a/src/CompilableFile.cs b/src/CompilableFile.cs
index abb935b..cf0eaa3 100644
--- a/src/CompilableFile.cs
+++ b/src/CompilableFile.cs
@@ -56,7 +56,7 @@ internal void Compile(Action callback)
{
if (CompilationQueuedAt > 0f)
{
- var ago = Interface.Oxide.Now - CompilationQueuedAt;
+ float ago = Interface.Oxide.Now - CompilationQueuedAt;
Interface.Oxide.LogDebug($"Plugin compilation is already queued: {ScriptName} ({ago:0.000} ago)");
//RemoteLogger.Debug($"Plugin compilation is already queued: {ScriptName} ({ago:0.000} ago)");
return;
@@ -130,7 +130,7 @@ internal void OnCompilationTimeout()
internal bool HasBeenModified()
{
- var lastModifiedAt = LastModifiedAt;
+ DateTime lastModifiedAt = LastModifiedAt;
CheckLastModificationTime();
return LastModifiedAt != lastModifiedAt;
}
@@ -142,8 +142,11 @@ internal void CheckLastModificationTime()
LastModifiedAt = default(DateTime);
return;
}
- var modifiedTime = GetLastModificationTime();
- if (modifiedTime != default(DateTime)) LastModifiedAt = modifiedTime;
+ DateTime modifiedTime = GetLastModificationTime();
+ if (modifiedTime != default(DateTime))
+ {
+ LastModifiedAt = modifiedTime;
+ }
}
internal DateTime GetLastModificationTime()
@@ -169,7 +172,11 @@ protected virtual void OnCompilationRequested()
protected virtual void InitFailed(string message = null)
{
- if (message != null) Interface.Oxide.LogError(message);
+ if (message != null)
+ {
+ Interface.Oxide.LogError(message);
+ }
+
LoadCallback?.Invoke(null);
}
}
diff --git a/src/CompilablePlugin.cs b/src/CompilablePlugin.cs
index e0a3795..3e1dc70 100644
--- a/src/CompilablePlugin.cs
+++ b/src/CompilablePlugin.cs
@@ -44,7 +44,7 @@ internal void LoadPlugin(Action callback = null)
return;
}
- var type = CompiledAssembly.LoadedAssembly.GetType($"Oxide.Plugins.{Name}");
+ Type type = CompiledAssembly.LoadedAssembly.GetType($"Oxide.Plugins.{Name}");
if (type == null)
{
InitFailed($"Unable to find main plugin class: {Name}");
@@ -63,7 +63,7 @@ internal void LoadPlugin(Action callback = null)
}
catch (TargetInvocationException invocationException)
{
- var ex = invocationException.InnerException;
+ Exception ex = invocationException.InnerException;
InitFailed($"Unable to load {ScriptName}. {ex.ToString()}");
return;
}
@@ -95,7 +95,11 @@ internal void LoadPlugin(Action callback = null)
return;
}
- if (!CompiledAssembly.IsBatch) LastGoodAssembly = CompiledAssembly;
+ if (!CompiledAssembly.IsBatch)
+ {
+ LastGoodAssembly = CompiledAssembly;
+ }
+
callback?.Invoke(plugin);
});
}
@@ -105,11 +109,19 @@ internal override void OnCompilationStarted()
base.OnCompilationStarted();
// Enqueue compilation of any plugins which depend on this plugin
- foreach (var plugin in Interface.Oxide.RootPluginManager.GetPlugins())
+ foreach (Core.Plugins.Plugin plugin in Interface.Oxide.RootPluginManager.GetPlugins())
{
- if (!(plugin is CSharpPlugin)) continue;
- var compilablePlugin = CSharpPluginLoader.GetCompilablePlugin(Directory, plugin.Name);
- if (!compilablePlugin.Requires.Contains(Name)) continue;
+ if (!(plugin is CSharpPlugin))
+ {
+ continue;
+ }
+
+ CompilablePlugin compilablePlugin = CSharpPluginLoader.GetCompilablePlugin(Directory, plugin.Name);
+ if (!compilablePlugin.Requires.Contains(Name))
+ {
+ continue;
+ }
+
compilablePlugin.CompiledAssembly = null;
Loader.Load(compilablePlugin);
}
diff --git a/src/Compilation.cs b/src/Compilation.cs
index 938d4ff..a9ea977 100644
--- a/src/Compilation.cs
+++ b/src/Compilation.cs
@@ -38,9 +38,12 @@ internal Compilation(int id, Action callback, CompilablePlugin[] pl
this.callback = callback;
this.queuedPlugins = new ConcurrentHashSet(plugins);
- if (Current == null) Current = this;
+ if (Current == null)
+ {
+ Current = this;
+ }
- foreach (var plugin in plugins)
+ foreach (CompilablePlugin plugin in plugins)
{
plugin.CompilerErrors = null;
plugin.OnCompilationStarted();
@@ -48,7 +51,7 @@ internal Compilation(int id, Action callback, CompilablePlugin[] pl
includePath = Path.Combine(Interface.Oxide.PluginDirectory, "include");
extensionNames = Interface.Oxide.GetAllExtensions().Select(ext => ext.Name).ToArray();
- var gameExtension = Interface.Oxide.GetAllExtensions().SingleOrDefault(ext => ext.IsGameExtension);
+ Core.Extensions.Extension gameExtension = Interface.Oxide.GetAllExtensions().SingleOrDefault(ext => ext.IsGameExtension);
gameExtensionName = gameExtension?.Name.ToUpper();
gameExtensionNamespace = gameExtension?.GetType().Namespace;
gameExtensionBranch = gameExtension?.Branch?.ToUpper();
@@ -64,22 +67,31 @@ internal void Completed(byte[] rawAssembly = null)
{
endedAt = Interface.Oxide.Now;
if (plugins.Count > 0 && rawAssembly != null)
+ {
compiledAssembly = new CompiledAssembly(name, plugins.ToArray(), rawAssembly, duration);
+ }
+
Interface.Oxide.NextTick(() => callback(this));
}
internal void Add(CompilablePlugin plugin)
{
- if (!queuedPlugins.Add(plugin)) return;
+ if (!queuedPlugins.Add(plugin))
+ {
+ return;
+ }
plugin.Loader.PluginLoadingStarted(plugin);
plugin.CompilerErrors = null;
plugin.OnCompilationStarted();
- foreach (var pl in Interface.Oxide.RootPluginManager.GetPlugins().Where(pl => pl is CSharpPlugin))
+ foreach (Core.Plugins.Plugin pl in Interface.Oxide.RootPluginManager.GetPlugins().Where(pl => pl is CSharpPlugin))
{
- var loadedPlugin = CSharpPluginLoader.GetCompilablePlugin(plugin.Directory, pl.Name);
- if (!loadedPlugin.Requires.Contains(plugin.Name)) continue;
+ CompilablePlugin loadedPlugin = CSharpPluginLoader.GetCompilablePlugin(plugin.Directory, pl.Name);
+ if (!loadedPlugin.Requires.Contains(plugin.Name))
+ {
+ continue;
+ }
AddDependency(loadedPlugin);
}
@@ -87,9 +99,12 @@ internal void Add(CompilablePlugin plugin)
internal bool IncludesRequiredPlugin(string name)
{
- if (referencedPlugins.Contains(name)) return true;
+ if (referencedPlugins.Contains(name))
+ {
+ return true;
+ }
- var compilablePlugin = plugins.SingleOrDefault(pl => pl.Name == name);
+ CompilablePlugin compilablePlugin = plugins.SingleOrDefault(pl => pl.Name == name);
return compilablePlugin != null && compilablePlugin.CompilerErrors == null;
}
@@ -103,20 +118,27 @@ internal void Prepare(Action callback)
references.Clear();
// Include references made by the CSharpPlugins project
- foreach (var filename in CSharpPluginLoader.PluginReferences)
+ foreach (string filename in CSharpPluginLoader.PluginReferences)
{
if (File.Exists(Path.Combine(Interface.Oxide.ExtensionDirectory, filename + ".dll")))
+ {
references[filename + ".dll"] = new CompilerFile(Interface.Oxide.ExtensionDirectory, filename + ".dll");
+ }
+
if (File.Exists(Path.Combine(Interface.Oxide.ExtensionDirectory, filename + ".exe")))
+ {
references[filename + ".exe"] = new CompilerFile(Interface.Oxide.ExtensionDirectory, filename + ".exe");
+ }
}
//Interface.Oxide.LogDebug("Preparing compilation");
- CompilablePlugin plugin;
- while (queuedPlugins.TryDequeue(out plugin))
+ while (queuedPlugins.TryDequeue(out CompilablePlugin plugin))
{
- if (Current == null) Current = this;
+ if (Current == null)
+ {
+ Current = this;
+ }
if (!CacheScriptLines(plugin) || plugin.ScriptLines.Length < 1)
{
@@ -165,28 +187,40 @@ private void PreparseScript(CompilablePlugin plugin)
plugin.IncludePaths.Clear();
plugin.Requires.Clear();
- var parsingNamespace = false;
- for (var i = 0; i < plugin.ScriptLines.Length; i++)
+ bool parsingNamespace = false;
+ for (int i = 0; i < plugin.ScriptLines.Length; i++)
{
- var line = plugin.ScriptLines[i].Trim();
- if (line.Length < 1) continue;
+ string line = plugin.ScriptLines[i].Trim();
+ if (line.Length < 1)
+ {
+ continue;
+ }
Match match;
if (parsingNamespace)
{
// Skip blank lines and opening brace at the top of the namespace block
match = Regex.Match(line, @"^\s*\{?\s*$", RegexOptions.IgnoreCase);
- if (match.Success) continue;
+ if (match.Success)
+ {
+ continue;
+ }
// Skip class custom attributes
match = Regex.Match(line, @"^\s*\[", RegexOptions.IgnoreCase);
- if (match.Success) continue;
+ if (match.Success)
+ {
+ continue;
+ }
// Detect main plugin class name
match = Regex.Match(line, @"^\s*(?:public|private|protected|internal)?\s*class\s+(\S+)\s+\:\s+\S+Plugin\s*$", RegexOptions.IgnoreCase);
- if (!match.Success) break;
+ if (!match.Success)
+ {
+ break;
+ }
- var className = match.Groups[1].Value;
+ string className = match.Groups[1].Value;
if (className != plugin.Name)
{
Interface.Oxide.LogError($"Plugin filename {plugin.ScriptName}.cs must match the main class {className} (should be {className}.cs)");
@@ -201,7 +235,7 @@ private void PreparseScript(CompilablePlugin plugin)
match = Regex.Match(line, @"^//\s*Requires:\s*(\S+?)(\.cs)?\s*$", RegexOptions.IgnoreCase);
if (match.Success)
{
- var dependencyName = match.Groups[1].Value;
+ string dependencyName = match.Groups[1].Value;
plugin.Requires.Add(dependencyName);
if (!File.Exists(Path.Combine(plugin.Directory, dependencyName + ".cs")))
{
@@ -212,7 +246,7 @@ private void PreparseScript(CompilablePlugin plugin)
}
//Interface.Oxide.LogDebug(plugin.Name + " plugin requires dependency: " + dependency_name);
- var dependencyPlugin = CSharpPluginLoader.GetCompilablePlugin(plugin.Directory, dependencyName);
+ CompilablePlugin dependencyPlugin = CSharpPluginLoader.GetCompilablePlugin(plugin.Directory, dependencyName);
AddDependency(dependencyPlugin);
continue;
}
@@ -221,14 +255,17 @@ private void PreparseScript(CompilablePlugin plugin)
match = Regex.Match(line, @"^//\s*Reference:\s*(\S+)\s*$", RegexOptions.IgnoreCase);
if (match.Success)
{
- var result = match.Groups[1].Value;
+ string result = match.Groups[1].Value;
if (!result.StartsWith("Oxide.") && !result.StartsWith("Newtonsoft.Json") && !result.StartsWith("protobuf-net") && !result.StartsWith("Rust."))
{
AddReference(plugin, result);
Interface.Oxide.LogInfo("Added '// Reference: {0}' in plugin '{1}'", result, plugin.Name);
}
else
+ {
Interface.Oxide.LogWarning("Ignored unnecessary '// Reference: {0}' in plugin '{1}'", result, plugin.Name);
+ }
+
continue;
}
@@ -236,35 +273,49 @@ private void PreparseScript(CompilablePlugin plugin)
match = Regex.Match(line, @"^\s*using\s+(Oxide\.(?:Core|Ext|Game)\.(?:[^\.]+))[^;]*;.*$", RegexOptions.IgnoreCase);
if (match.Success)
{
- var result = match.Groups[1].Value;
- var newResult = Regex.Replace(result, @"Oxide\.[\w]+\.([\w]+)", "Oxide.$1");
+ string result = match.Groups[1].Value;
+ string newResult = Regex.Replace(result, @"Oxide\.[\w]+\.([\w]+)", "Oxide.$1");
if (!string.IsNullOrEmpty(newResult) && File.Exists(Path.Combine(Interface.Oxide.ExtensionDirectory, newResult + ".dll")))
+ {
AddReference(plugin, newResult);
+ }
else
+ {
AddReference(plugin, result);
+ }
+
continue;
}
// Start parsing the Oxide.Plugins namespace contents
match = Regex.Match(line, @"^\s*namespace Oxide\.Plugins\s*(\{\s*)?$", RegexOptions.IgnoreCase);
- if (match.Success) parsingNamespace = true;
+ if (match.Success)
+ {
+ parsingNamespace = true;
+ }
}
}
private void ResolveReferences(CompilablePlugin plugin)
{
- foreach (var reference in plugin.References)
+ foreach (string reference in plugin.References)
{
- var match = Regex.Match(reference, @"^(Oxide\.(?:Ext|Game)\.(.+))$", RegexOptions.IgnoreCase);
- if (!match.Success) continue;
+ Match match = Regex.Match(reference, @"^(Oxide\.(?:Ext|Game)\.(.+))$", RegexOptions.IgnoreCase);
+ if (!match.Success)
+ {
+ continue;
+ }
- var fullName = match.Groups[1].Value;
- var name = match.Groups[2].Value;
- if (extensionNames.Contains(name)) continue;
+ string fullName = match.Groups[1].Value;
+ string name = match.Groups[2].Value;
+ if (extensionNames.Contains(name))
+ {
+ continue;
+ }
if (Directory.Exists(includePath))
{
- var includeFilePath = Path.Combine(includePath, $"Ext.{name}.cs");
+ string includeFilePath = Path.Combine(includePath, $"Ext.{name}.cs");
if (File.Exists(includeFilePath))
{
plugin.IncludePaths.Add(includeFilePath);
@@ -272,7 +323,7 @@ private void ResolveReferences(CompilablePlugin plugin)
}
}
- var message = $"{fullName} is referenced by {plugin.Name} plugin but is not loaded! An appropriate include file needs to be saved to plugins\\include\\Ext.{name}.cs if this extension is not required.";
+ string message = $"{fullName} is referenced by {plugin.Name} plugin but is not loaded! An appropriate include file needs to be saved to plugins\\include\\Ext.{name}.cs if this extension is not required.";
Interface.Oxide.LogError(message);
plugin.CompilerErrors = message;
RemovePlugin(plugin);
@@ -281,15 +332,20 @@ private void ResolveReferences(CompilablePlugin plugin)
private void AddDependency(CompilablePlugin plugin)
{
- if (plugin.IsLoading || plugins.Contains(plugin) || queuedPlugins.Contains(plugin)) return;
+ if (plugin.IsLoading || plugins.Contains(plugin) || queuedPlugins.Contains(plugin))
+ {
+ return;
+ }
- var compiledDependency = plugin.CompiledAssembly;
+ CompiledAssembly compiledDependency = plugin.CompiledAssembly;
if (compiledDependency != null && !compiledDependency.IsOutdated())
{
// The dependency already has a compiled assembly which is up to date
referencedPlugins.Add(plugin.Name);
if (!references.ContainsKey(compiledDependency.Name))
+ {
references[compiledDependency.Name] = new CompilerFile(compiledDependency.Name, compiledDependency.RawAssembly);
+ }
}
else
{
@@ -300,7 +356,7 @@ private void AddDependency(CompilablePlugin plugin)
private void AddReference(CompilablePlugin plugin, string assemblyName)
{
- var path = Path.Combine(Interface.Oxide.ExtensionDirectory, assemblyName + ".dll");
+ string path = Path.Combine(Interface.Oxide.ExtensionDirectory, assemblyName + ".dll");
if (!File.Exists(path))
{
if (assemblyName.StartsWith("Oxide."))
@@ -331,12 +387,15 @@ private void AddReference(CompilablePlugin plugin, string assemblyName)
AddReference(plugin, assembly.GetName());
// Include references made by the referenced assembly
- foreach (var reference in assembly.GetReferencedAssemblies())
+ foreach (AssemblyName reference in assembly.GetReferencedAssemblies())
{
// TODO: Fix Oxide.References to avoid these and other dependency conflicts
- if (reference.Name.StartsWith("Newtonsoft.Json") || reference.Name.StartsWith("Rust.Workshop")) continue;
+ if (reference.Name.StartsWith("Newtonsoft.Json") || reference.Name.StartsWith("Rust.Workshop"))
+ {
+ continue;
+ }
- var referencePath = Path.Combine(Interface.Oxide.ExtensionDirectory, reference.Name + ".dll");
+ string referencePath = Path.Combine(Interface.Oxide.ExtensionDirectory, reference.Name + ".dll");
if (!File.Exists(referencePath))
{
Interface.Oxide.LogWarning($"Reference {reference.Name}.dll from {assembly.GetName().Name}.dll not found");
@@ -349,14 +408,18 @@ private void AddReference(CompilablePlugin plugin, string assemblyName)
private void AddReference(CompilablePlugin plugin, AssemblyName reference)
{
- var filename = reference.Name + ".dll";
- if (!references.ContainsKey(filename)) references[filename] = new CompilerFile(Interface.Oxide.ExtensionDirectory, filename);
+ string filename = reference.Name + ".dll";
+ if (!references.ContainsKey(filename))
+ {
+ references[filename] = new CompilerFile(Interface.Oxide.ExtensionDirectory, filename);
+ }
+
plugin.References.Add(reference.Name);
}
private bool CacheScriptLines(CompilablePlugin plugin)
{
- var waitingForAccess = false;
+ bool waitingForAccess = false;
while (true)
{
try
@@ -372,11 +435,18 @@ private bool CacheScriptLines(CompilablePlugin plugin)
plugin.CheckLastModificationTime();
if (plugin.LastCachedScriptAt != plugin.LastModifiedAt)
{
- using (var reader = File.OpenText(plugin.ScriptPath))
+ using (StreamReader reader = File.OpenText(plugin.ScriptPath))
{
- var lines = new List();
- while (!reader.EndOfStream) lines.Add(reader.ReadLine());
- if (!string.IsNullOrEmpty(gameExtensionName)) lines.Insert(0, $"#define {gameExtensionName}");
+ List lines = new List();
+ while (!reader.EndOfStream)
+ {
+ lines.Add(reader.ReadLine());
+ }
+
+ if (!string.IsNullOrEmpty(gameExtensionName))
+ {
+ lines.Insert(0, $"#define {gameExtensionName}");
+ }
if (!string.IsNullOrEmpty(gameExtensionName))
{
@@ -393,7 +463,9 @@ private bool CacheScriptLines(CompilablePlugin plugin)
}
plugin.LastCachedScriptAt = plugin.LastModifiedAt;
if (plugins.Remove(plugin))
+ {
queuedPlugins.Add(plugin);
+ }
}
return true;
}
@@ -411,25 +483,40 @@ private bool CacheScriptLines(CompilablePlugin plugin)
private void CacheModifiedScripts()
{
- var modifiedPlugins = plugins.Where(pl => pl.ScriptLines == null || pl.HasBeenModified() || pl.LastCachedScriptAt != pl.LastModifiedAt).ToArray();
- if (modifiedPlugins.Length < 1) return;
+ CompilablePlugin[] modifiedPlugins = plugins.Where(pl => pl.ScriptLines == null || pl.HasBeenModified() || pl.LastCachedScriptAt != pl.LastModifiedAt).ToArray();
+ if (modifiedPlugins.Length < 1)
+ {
+ return;
+ }
+
+ foreach (CompilablePlugin plugin in modifiedPlugins)
+ {
+ CacheScriptLines(plugin);
+ }
- foreach (var plugin in modifiedPlugins) CacheScriptLines(plugin);
Thread.Sleep(100);
CacheModifiedScripts();
}
private void RemovePlugin(CompilablePlugin plugin)
{
- if (plugin.LastCompiledAt == default(DateTime)) return;
+ if (plugin.LastCompiledAt == default(DateTime))
+ {
+ return;
+ }
queuedPlugins.Remove(plugin);
plugins.Remove(plugin);
plugin.OnCompilationFailed();
// Remove plugins which are required by this plugin if they are only being compiled for this requirement
- foreach (var requiredPlugin in plugins.Where(pl => !pl.IsCompilationNeeded && plugin.Requires.Contains(pl.Name)).ToArray())
- if (!plugins.Any(pl => pl.Requires.Contains(requiredPlugin.Name))) RemovePlugin(requiredPlugin);
+ foreach (CompilablePlugin requiredPlugin in plugins.Where(pl => !pl.IsCompilationNeeded && plugin.Requires.Contains(pl.Name)).ToArray())
+ {
+ if (!plugins.Any(pl => pl.Requires.Contains(requiredPlugin.Name)))
+ {
+ RemovePlugin(requiredPlugin);
+ }
+ }
}
}
}
diff --git a/src/CompiledAssembly.cs b/src/CompiledAssembly.cs
index bd950b5..b369dff 100644
--- a/src/CompiledAssembly.cs
+++ b/src/CompiledAssembly.cs
@@ -64,13 +64,20 @@ public void LoadAssembly(Action callback)
IsLoading = true;
loadCallbacks.Add(callback);
- if (isPatching) return;
+ if (isPatching)
+ {
+ return;
+ }
PatchAssembly(rawAssembly =>
{
if (rawAssembly == null)
{
- foreach (var cb in loadCallbacks) cb(true);
+ foreach (Action cb in loadCallbacks)
+ {
+ cb(true);
+ }
+
loadCallbacks.Clear();
IsLoading = false;
return;
@@ -79,7 +86,11 @@ public void LoadAssembly(Action callback)
LoadedAssembly = Assembly.Load(rawAssembly);
isLoaded = true;
- foreach (var cb in loadCallbacks) cb(true);
+ foreach (Action cb in loadCallbacks)
+ {
+ cb(true);
+ }
+
loadCallbacks.Clear();
IsLoading = false;
@@ -95,7 +106,7 @@ private void PatchAssembly(Action callback)
return;
}
- var startedAt = Interface.Oxide.Now;
+ float startedAt = Interface.Oxide.Now;
isPatching = true;
ThreadPool.QueueUserWorkItem(_ =>
@@ -103,25 +114,27 @@ private void PatchAssembly(Action callback)
try
{
AssemblyDefinition definition;
- using (var stream = new MemoryStream(RawAssembly))
+ using (MemoryStream stream = new MemoryStream(RawAssembly))
+ {
definition = AssemblyDefinition.ReadAssembly(stream);
+ }
- var exceptionConstructor = typeof(UnauthorizedAccessException).GetConstructor(new[] { typeof(string) });
- var securityException = definition.MainModule.Import(exceptionConstructor);
+ ConstructorInfo exceptionConstructor = typeof(UnauthorizedAccessException).GetConstructor(new[] { typeof(string) });
+ MethodReference securityException = definition.MainModule.Import(exceptionConstructor);
Action patchModuleType = null;
patchModuleType = type =>
{
- foreach (var method in type.Methods)
+ foreach (MethodDefinition method in type.Methods)
{
- var changedMethod = false;
+ bool changedMethod = false;
if (method.Body == null)
{
if (method.HasPInvokeInfo)
{
method.Attributes &= ~MethodAttributes.PInvokeImpl;
- var body = new MethodBody(method);
+ MethodBody 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));
@@ -130,12 +143,15 @@ private void PatchAssembly(Action callback)
}
else
{
- var replacedMethod = false;
- foreach (var variable in method.Body.Variables)
+ bool replacedMethod = false;
+ foreach (VariableDefinition variable in method.Body.Variables)
{
- if (!IsNamespaceBlacklisted(variable.VariableType.FullName)) continue;
+ if (!IsNamespaceBlacklisted(variable.VariableType.FullName))
+ {
+ continue;
+ }
- var body = new MethodBody(method);
+ MethodBody 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));
@@ -143,21 +159,28 @@ private void PatchAssembly(Action callback)
replacedMethod = true;
break;
}
- if (replacedMethod) continue;
+ if (replacedMethod)
+ {
+ continue;
+ }
- var instructions = method.Body.Instructions;
- var ilProcessor = method.Body.GetILProcessor();
- var first = instructions.First();
+ References::Mono.Collections.Generic.Collection instructions = method.Body.Instructions;
+ ILProcessor ilProcessor = method.Body.GetILProcessor();
+ Instruction first = instructions.First();
- var i = 0;
+ int i = 0;
while (i < instructions.Count)
{
- if (changedMethod) break;
- var instruction = instructions[i];
+ if (changedMethod)
+ {
+ break;
+ }
+
+ Instruction instruction = instructions[i];
if (instruction.OpCode == OpCodes.Ldtoken)
{
- var operand = instruction.Operand as IMetadataTokenProvider;
- var token = operand?.ToString();
+ IMetadataTokenProvider operand = instruction.Operand as IMetadataTokenProvider;
+ string token = operand?.ToString();
if (IsNamespaceBlacklisted(token))
{
ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {token}"));
@@ -168,8 +191,8 @@ private void PatchAssembly(Action callback)
}
else if (instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Calli || instruction.OpCode == OpCodes.Callvirt || instruction.OpCode == OpCodes.Ldftn)
{
- var methodCall = instruction.Operand as MethodReference;
- var fullNamespace = methodCall?.DeclaringType.FullName;
+ MethodReference methodCall = instruction.Operand as MethodReference;
+ string fullNamespace = methodCall?.DeclaringType.FullName;
if ((fullNamespace == "System.Type" && methodCall.Name == "GetType") || IsNamespaceBlacklisted(fullNamespace))
{
@@ -181,8 +204,8 @@ private void PatchAssembly(Action callback)
}
else if (instruction.OpCode == OpCodes.Ldfld)
{
- var fieldType = instruction.Operand as FieldReference;
- var fullNamespace = fieldType?.FieldType.FullName;
+ FieldReference fieldType = instruction.Operand as FieldReference;
+ string 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}"));
@@ -211,28 +234,35 @@ private void PatchAssembly(Action callback)
}*/
}
}
- foreach (var nestedType in type.NestedTypes)
+ foreach (TypeDefinition nestedType in type.NestedTypes)
+ {
patchModuleType(nestedType);
+ }
};
- foreach (var type in definition.MainModule.Types)
+ foreach (TypeDefinition type in definition.MainModule.Types)
{
patchModuleType(type);
- if (IsCompilerGenerated(type)) continue;
+ if (IsCompilerGenerated(type))
+ {
+ continue;
+ }
if (type.Namespace == "Oxide.Plugins")
{
if (PluginNames.Contains(type.Name))
{
- var constructor =
+ MethodDefinition 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);
+ CompilablePlugin plugin = CompilablePlugins.SingleOrDefault(p => p.Name == type.Name);
if (plugin != null)
+ {
plugin.CompilerErrors = "Primary constructor in main class must be public";
+ }
}
else
{
@@ -250,21 +280,27 @@ private void PatchAssembly(Action callback)
else if (type.FullName != "")
{
if (!PluginNames.Any(plugin => type.FullName.StartsWith($"Oxide.Plugins.{plugin}")))
+ {
Interface.Oxide.LogWarning(PluginNames.Length == 1
? $"{PluginNames[0]} has polluted the global namespace by defining {type.FullName}"
: $"A plugin has polluted the global namespace by defining {type.FullName}");
+ }
}
}
// TODO: Why is there no error on boot using this?
- foreach (var type in definition.MainModule.Types)
+ foreach (TypeDefinition 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))
+ if (type.Namespace != "Oxide.Plugins" || !PluginNames.Contains(type.Name))
{
- foreach (var parameter in m.Parameters)
+ continue;
+ }
+
+ foreach (MethodDefinition m in type.Methods.Where(m => !m.IsStatic && !m.HasGenericParameters && !m.ReturnType.IsGenericParameter && !m.IsSetter && !m.IsGetter))
+ {
+ foreach (ParameterDefinition parameter in m.Parameters)
{
- foreach (var attribute in parameter.CustomAttributes)
+ foreach (CustomAttribute attribute in parameter.CustomAttributes)
{
//Interface.Oxide.LogInfo($"{m.FullName} - {parameter.Name} - {attribute.Constructor.FullName}");
}
@@ -272,7 +308,7 @@ private void PatchAssembly(Action callback)
}
}
- using (var stream = new MemoryStream())
+ using (MemoryStream stream = new MemoryStream())
{
definition.Write(stream);
PatchedAssembly = stream.ToArray();
@@ -304,10 +340,18 @@ private void PatchAssembly(Action callback)
private static bool IsNamespaceBlacklisted(string fullNamespace)
{
- foreach (var namespaceName in BlacklistedNamespaces)
+ foreach (string namespaceName in BlacklistedNamespaces)
{
- if (!fullNamespace.StartsWith(namespaceName)) continue;
- if (WhitelistedNamespaces.Any(fullNamespace.StartsWith)) continue;
+ if (!fullNamespace.StartsWith(namespaceName))
+ {
+ continue;
+ }
+
+ if (WhitelistedNamespaces.Any(fullNamespace.StartsWith))
+ {
+ continue;
+ }
+
return true;
}
return false;
diff --git a/src/Covalence/Plugin.cs b/src/Covalence/Plugin.cs
index a5d1ac9..224152f 100644
--- a/src/Covalence/Plugin.cs
+++ b/src/Covalence/Plugin.cs
@@ -78,15 +78,22 @@ protected void LogError(string format, params object[] args)
///
public override void HandleAddedToManager(PluginManager manager)
{
- foreach (var method in GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
+ foreach (MethodInfo method in GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
{
- var commandAttribute = method.GetCustomAttributes(typeof(CommandAttribute), true);
- var permissionAttribute = method.GetCustomAttributes(typeof(PermissionAttribute), true);
- if (commandAttribute.Length <= 0) continue;
+ object[] commandAttribute = method.GetCustomAttributes(typeof(CommandAttribute), true);
+ object[] permissionAttribute = method.GetCustomAttributes(typeof(PermissionAttribute), true);
+ if (commandAttribute.Length <= 0)
+ {
+ continue;
+ }
+
+ CommandAttribute cmd = commandAttribute[0] as CommandAttribute;
+ PermissionAttribute perm = permissionAttribute.Length <= 0 ? null : permissionAttribute[0] as PermissionAttribute;
+ if (cmd == null)
+ {
+ continue;
+ }
- var cmd = commandAttribute[0] as CommandAttribute;
- var perm = permissionAttribute.Length <= 0 ? null : permissionAttribute[0] as PermissionAttribute;
- if (cmd == null) continue;
AddCovalenceCommand(cmd.Commands, perm?.Permission, (caller, command, args) =>
{
CallHook(method.Name, caller, command, args);
diff --git a/src/DirectCallMethod.cs b/src/DirectCallMethod.cs
index 6e031fc..be8b6db 100644
--- a/src/DirectCallMethod.cs
+++ b/src/DirectCallMethod.cs
@@ -51,29 +51,34 @@ public DirectCallMethod(ModuleDefinition module, TypeDefinition type)
stringEquals = module.Import(typeof(string).GetMethod("Equals", new[] { typeof(string) }));
// Copy method definition from base class
- var base_assembly = AssemblyDefinition.ReadAssembly(Path.Combine(Interface.Oxide.ExtensionDirectory, "Oxide.CSharp.dll"));
- var base_module = base_assembly.MainModule;
- var base_type = module.Import(base_assembly.MainModule.GetType("Oxide.Plugins.CSharpPlugin")).Resolve();
- var base_method = module.Import(base_type.Methods.First(method => method.Name == "DirectCallHook")).Resolve();
+ AssemblyDefinition base_assembly = AssemblyDefinition.ReadAssembly(Path.Combine(Interface.Oxide.ExtensionDirectory, "Oxide.CSharp.dll"));
+ ModuleDefinition base_module = base_assembly.MainModule;
+ TypeDefinition base_type = module.Import(base_assembly.MainModule.GetType("Oxide.Plugins.CSharpPlugin")).Resolve();
+ MethodDefinition base_method = module.Import(base_type.Methods.First(method => method.Name == "DirectCallHook")).Resolve();
// Create method override based on virtual method signature
method = new MethodDefinition(base_method.Name, base_method.Attributes, base_module.Import(base_method.ReturnType)) { DeclaringType = type };
- foreach (var parameter in base_method.Parameters)
+ foreach (ParameterDefinition parameter in base_method.Parameters)
{
- var new_param = new ParameterDefinition(parameter.Name, parameter.Attributes, base_module.Import(parameter.ParameterType))
+ ParameterDefinition new_param = new ParameterDefinition(parameter.Name, parameter.Attributes, base_module.Import(parameter.ParameterType))
{
IsOut = parameter.IsOut,
Constant = parameter.Constant,
MarshalInfo = parameter.MarshalInfo,
IsReturnValue = parameter.IsReturnValue
};
- foreach (var attribute in parameter.CustomAttributes)
+ foreach (CustomAttribute attribute in parameter.CustomAttributes)
+ {
new_param.CustomAttributes.Add(new CustomAttribute(module.Import(attribute.Constructor)));
+ }
+
method.Parameters.Add(new_param);
}
- foreach (var attribute in base_method.CustomAttributes)
+ foreach (CustomAttribute attribute in base_method.CustomAttributes)
+ {
method.CustomAttributes.Add(new CustomAttribute(module.Import(attribute.Constructor)));
+ }
method.ImplAttributes = base_method.ImplAttributes;
method.SemanticsAttributes = base_method.SemanticsAttributes;
@@ -100,7 +105,7 @@ public DirectCallMethod(ModuleDefinition module, TypeDefinition type)
// Check for name null or empty
AddInstruction(OpCodes.Ldarg_1);
AddInstruction(OpCodes.Call, isNullOrEmpty);
- var empty = AddInstruction(OpCodes.Brfalse, body.Instructions[0]);
+ Instruction empty = AddInstruction(OpCodes.Brfalse, body.Instructions[0]);
Return(false);
// Get method name length
@@ -113,51 +118,64 @@ public DirectCallMethod(ModuleDefinition module, TypeDefinition type)
AddInstruction(OpCodes.Stloc_1);
// Find all hook methods defined by the plugin
- foreach (var m in type.Methods.Where(m => !m.IsStatic && (m.IsPrivate || IsHookMethod(m)) && !m.HasGenericParameters && !m.ReturnType.IsGenericParameter && m.DeclaringType == type && !m.IsSetter && !m.IsGetter))
+ foreach (MethodDefinition m in type.Methods.Where(m => !m.IsStatic && (m.IsPrivate || IsHookMethod(m)) && !m.HasGenericParameters && !m.ReturnType.IsGenericParameter && m.DeclaringType == type && !m.IsSetter && !m.IsGetter))
{
//ignore compiler generated
- if (m.Name.Contains("<")) continue;
+ if (m.Name.Contains("<"))
+ {
+ continue;
+ }
- var name = m.Name;
+ string name = m.Name;
if (m.Parameters.Count > 0)
+ {
name += $"({string.Join(", ", m.Parameters.Select(x => x.ParameterType.ToString().Replace("/", "+").Replace("<", "[").Replace(">", "]")).ToArray())})";
+ }
- if (!hookMethods.ContainsKey(name)) hookMethods[name] = m;
+ if (!hookMethods.ContainsKey(name))
+ {
+ hookMethods[name] = m;
+ }
}
// Build a hook method name trie
- var root_node = new Node();
- foreach (var method_name in hookMethods.Keys)
+ Node root_node = new Node();
+ foreach (string method_name in hookMethods.Keys)
{
- var current_node = root_node;
- for (var i = 1; i <= method_name.Length; i++)
+ Node current_node = root_node;
+ for (int i = 1; i <= method_name.Length; i++)
{
- var letter = method_name[i - 1];
- Node next_node;
- if (!current_node.Edges.TryGetValue(letter, out next_node))
+ char letter = method_name[i - 1];
+ if (!current_node.Edges.TryGetValue(letter, out Node next_node))
{
next_node = new Node { Parent = current_node, Char = letter };
current_node.Edges[letter] = next_node;
}
- if (i == method_name.Length) next_node.Name = method_name;
+ if (i == method_name.Length)
+ {
+ next_node.Name = method_name;
+ }
+
current_node = next_node;
}
}
// Build conditional method call logic from trie nodes
- var n = 1;
- foreach (var edge in root_node.Edges.Keys)
+ int n = 1;
+ foreach (char edge in root_node.Edges.Keys)
+ {
BuildNode(root_node.Edges[edge], n++);
+ }
// No valid method was found
endInstruction = Return(false);
- foreach (var instruction in jumpToEdgePlaceholderTargets.Keys)
+ foreach (Instruction instruction in jumpToEdgePlaceholderTargets.Keys)
{
instruction.Operand = jumpToEdgePlaceholderTargets[instruction].FirstInstruction;
}
- foreach (var instruction in jumpToEndPlaceholders)
+ foreach (Instruction instruction in jumpToEndPlaceholders)
{
instruction.Operand = endInstruction;
}
@@ -167,10 +185,12 @@ public DirectCallMethod(ModuleDefinition module, TypeDefinition type)
private bool IsHookMethod(MethodDefinition method)
{
- foreach (var attribute in method.CustomAttributes)
+ foreach (CustomAttribute attribute in method.CustomAttributes)
{
if (attribute.AttributeType.FullName == hook_attribute)
+ {
return true;
+ }
}
return false;
}
@@ -187,9 +207,14 @@ private void BuildNode(Node node, int edge_number)
// Check the char at the current position
if (edge_number == 1)
+ {
AddInstruction(OpCodes.Ldarg_1); //method_name
+ }
else
+ {
node.FirstInstruction = AddInstruction(OpCodes.Ldarg_1);
+ }
+
AddInstruction(OpCodes.Ldloc_1); // i
AddInstruction(OpCodes.Callvirt, getChars); // method_name[i]
AddInstruction(Ldc_I4_n(node.Char));
@@ -207,9 +232,12 @@ private void BuildNode(Node node, int edge_number)
if (node.Edges.Count == 1 && node.Name == null)
{
- var last_edge = node;
+ Node last_edge = node;
while (last_edge.Edges.Count == 1 && last_edge.Name == null)
+ {
last_edge = last_edge.Edges.Values.First();
+ }
+
if (last_edge.Edges.Count == 0 && last_edge.Name != null)
{
// There is only one remaining possible hook on this path
@@ -240,31 +268,37 @@ private void BuildNode(Node node, int edge_number)
AddInstruction(OpCodes.Ldloc_0);
// If the method name is longer than the current position
if (node.Edges.Count > 0)
+ {
JumpToEdge(node.Edges.Values.First());
+ }
else
+ {
JumpToEnd();
+ }
// Method has been found
CallMethod(hookMethods[node.Name]);
Return(true);
}
- var n = 1;
- foreach (var edge in node.Edges.Keys)
+ int n = 1;
+ foreach (char edge in node.Edges.Keys)
+ {
BuildNode(node.Edges[edge], n++);
+ }
}
private void CallMethod(MethodDefinition method)
{
- var paramDict = new Dictionary();
+ Dictionary paramDict = new Dictionary();
//check for ref/out param
- for (var i = 0; i < method.Parameters.Count; i++)
+ for (int i = 0; i < method.Parameters.Count; i++)
{
- var parameter = method.Parameters[i];
- var param = parameter.ParameterType as ByReferenceType;
+ ParameterDefinition parameter = method.Parameters[i];
+ ByReferenceType param = parameter.ParameterType as ByReferenceType;
if (param != null)
{
- var refParam = AddVariable(module.Import(param.ElementType));
+ VariableDefinition refParam = AddVariable(module.Import(param.ElementType));
AddInstruction(OpCodes.Ldarg_3); // object[] params
AddInstruction(Ldc_I4_n(i)); // param_number
AddInstruction(OpCodes.Ldelem_Ref);
@@ -274,13 +308,16 @@ private void CallMethod(MethodDefinition method)
}
}
- if (method.ReturnType.Name != "Void") AddInstruction(OpCodes.Ldarg_2); // out object ret
+ if (method.ReturnType.Name != "Void")
+ {
+ AddInstruction(OpCodes.Ldarg_2); // out object ret
+ }
AddInstruction(OpCodes.Ldarg_0); // this
- for (var i = 0; i < method.Parameters.Count; i++)
+ for (int i = 0; i < method.Parameters.Count; i++)
{
- var parameter = method.Parameters[i];
- var param = parameter.ParameterType as ByReferenceType;
+ ParameterDefinition parameter = method.Parameters[i];
+ ByReferenceType param = parameter.ParameterType as ByReferenceType;
if (param != null)
{
AddInstruction(OpCodes.Ldloca, paramDict[parameter]);
@@ -297,10 +334,10 @@ private void CallMethod(MethodDefinition method)
AddInstruction(OpCodes.Call, module.Import(method));
//handle ref/out params
- for (var i = 0; i < method.Parameters.Count; i++)
+ for (int i = 0; i < method.Parameters.Count; i++)
{
- var parameter = method.Parameters[i];
- var param = parameter.ParameterType as ByReferenceType;
+ ParameterDefinition parameter = method.Parameters[i];
+ ByReferenceType param = parameter.ParameterType as ByReferenceType;
if (param != null)
{
AddInstruction(OpCodes.Ldarg_3); // object[] params
@@ -313,21 +350,25 @@ private void CallMethod(MethodDefinition method)
if (method.ReturnType.Name != "Void")
{
- if (method.ReturnType.Name != "Object") AddInstruction(OpCodes.Box, module.Import(method.ReturnType));
+ if (method.ReturnType.Name != "Object")
+ {
+ AddInstruction(OpCodes.Box, module.Import(method.ReturnType));
+ }
+
AddInstruction(OpCodes.Stind_Ref);
}
}
private Instruction Return(bool value)
{
- var instruction = AddInstruction(Ldc_I4_n(value ? 1 : 0));
+ Instruction instruction = AddInstruction(Ldc_I4_n(value ? 1 : 0));
AddInstruction(OpCodes.Ret);
return instruction;
}
private void JumpToEdge(Node node)
{
- var instruction = AddInstruction(OpCodes.Bne_Un, body.Instructions[1]);
+ Instruction instruction = AddInstruction(OpCodes.Bne_Un, body.Instructions[1]);
jumpToEdgePlaceholderTargets[instruction] = node;
}
@@ -374,22 +415,58 @@ private Instruction AddInstruction(Instruction instruction)
public VariableDefinition AddVariable(TypeReference typeRef, string name = "")
{
- var def = new VariableDefinition(name, typeRef);
+ VariableDefinition def = new VariableDefinition(name, typeRef);
body.Variables.Add(def);
return def;
}
private Instruction Ldc_I4_n(int n)
{
- if (n == 0) return Instruction.Create(OpCodes.Ldc_I4_0);
- if (n == 1) return Instruction.Create(OpCodes.Ldc_I4_1);
- if (n == 2) return Instruction.Create(OpCodes.Ldc_I4_2);
- if (n == 3) return Instruction.Create(OpCodes.Ldc_I4_3);
- if (n == 4) return Instruction.Create(OpCodes.Ldc_I4_4);
- if (n == 5) return Instruction.Create(OpCodes.Ldc_I4_5);
- if (n == 6) return Instruction.Create(OpCodes.Ldc_I4_6);
- if (n == 7) return Instruction.Create(OpCodes.Ldc_I4_7);
- if (n == 8) return Instruction.Create(OpCodes.Ldc_I4_8);
+ if (n == 0)
+ {
+ return Instruction.Create(OpCodes.Ldc_I4_0);
+ }
+
+ if (n == 1)
+ {
+ return Instruction.Create(OpCodes.Ldc_I4_1);
+ }
+
+ if (n == 2)
+ {
+ return Instruction.Create(OpCodes.Ldc_I4_2);
+ }
+
+ if (n == 3)
+ {
+ return Instruction.Create(OpCodes.Ldc_I4_3);
+ }
+
+ if (n == 4)
+ {
+ return Instruction.Create(OpCodes.Ldc_I4_4);
+ }
+
+ if (n == 5)
+ {
+ return Instruction.Create(OpCodes.Ldc_I4_5);
+ }
+
+ if (n == 6)
+ {
+ return Instruction.Create(OpCodes.Ldc_I4_6);
+ }
+
+ if (n == 7)
+ {
+ return Instruction.Create(OpCodes.Ldc_I4_7);
+ }
+
+ if (n == 8)
+ {
+ return Instruction.Create(OpCodes.Ldc_I4_8);
+ }
+
return Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)n);
}
}
diff --git a/src/ObjectStream/Data/CompilerData.cs b/src/ObjectStream/Data/CompilerData.cs
index 8b259b8..d96604a 100644
--- a/src/ObjectStream/Data/CompilerData.cs
+++ b/src/ObjectStream/Data/CompilerData.cs
@@ -14,6 +14,7 @@ public CompilerData()
LoadDefaultReferences = false;
SdkVersion = "2";
}
+
public bool LoadDefaultReferences { get; set; }
public string OutputFile { get; set; }
public CompilerPlatform Platform { get; set; }
diff --git a/src/ObjectStream/IO/BindChanger.cs b/src/ObjectStream/IO/BindChanger.cs
index 2c91c02..e1b0253 100644
--- a/src/ObjectStream/IO/BindChanger.cs
+++ b/src/ObjectStream/IO/BindChanger.cs
@@ -8,12 +8,16 @@ public class BindChanger : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
- /*if (typeName.Contains(".")) typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
- if (typeName.Contains("+")) typeName = typeName.Substring(typeName.LastIndexOf("+", StringComparison.Ordinal) + 1);
+ /*if (typeName.Contains("."))
+ {
+ typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
+ }
+ if (typeName.Contains("+"))
+ {
+ typeName = typeName.Substring(typeName.LastIndexOf("+", StringComparison.Ordinal) + 1);
+ }
- var type = AppDomain.CurrentDomain.GetAssemblies()
- .SelectMany(x => x.GetTypes())
- .FirstOrDefault(x => x.Name.Equals(typeName));
+ Type type = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()).FirstOrDefault(x => x.Name.Equals(typeName));
return type != null ? Type.GetType(string.Format("{0}, {1}", type.FullName, Assembly.GetExecutingAssembly().FullName)) : null;*/
return Type.GetType(string.Format("{0}, {1}", typeName, Assembly.GetExecutingAssembly().FullName));
diff --git a/src/ObjectStream/IO/ObjectStreamWrapper.cs b/src/ObjectStream/IO/ObjectStreamWrapper.cs
index 2a3c34a..a93722e 100644
--- a/src/ObjectStream/IO/ObjectStreamWrapper.cs
+++ b/src/ObjectStream/IO/ObjectStreamWrapper.cs
@@ -39,7 +39,11 @@ public ObjectStreamWrapper(Stream inStream, Stream outStream)
public void Close()
{
- if (!_run) return;
+ if (!_run)
+ {
+ return;
+ }
+
_run = false;
try
{
@@ -55,7 +59,7 @@ public void Close()
public TRead ReadObject()
{
- var len = ReadLength();
+ int len = ReadLength();
return len == 0 ? null : ReadObject(len);
}
@@ -64,14 +68,22 @@ public TRead ReadObject()
private int ReadLength()
{
const int lensize = sizeof(int);
- var lenbuf = new byte[lensize];
- var bytesRead = _inStream.Read(lenbuf, 0, lensize);
- if (bytesRead == 0) return 0;
+ byte[] lenbuf = new byte[lensize];
+ int bytesRead = _inStream.Read(lenbuf, 0, lensize);
+ if (bytesRead == 0)
+ {
+ return 0;
+ }
+
if (bytesRead != lensize)
{
// TODO: Hack to ignore BOM
Array.Resize(ref lenbuf, Encoding.UTF8.GetPreamble().Length);
- if (Encoding.UTF8.GetPreamble().SequenceEqual(lenbuf)) return ReadLength();
+ if (Encoding.UTF8.GetPreamble().SequenceEqual(lenbuf))
+ {
+ return ReadLength();
+ }
+
throw new IOException(string.Format("Expected {0} bytes but read {1}", lensize, bytesRead));
}
return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(lenbuf, 0));
@@ -79,12 +91,15 @@ private int ReadLength()
private TRead ReadObject(int len)
{
- var data = new byte[len];
+ byte[] data = new byte[len];
int count;
int sum = 0;
while (len - sum > 0 && (count = _inStream.Read(data, sum, len - sum)) > 0)
+ {
sum += count;
- using (var memoryStream = new MemoryStream(data))
+ }
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
{
return (TRead)_binaryFormatter.Deserialize(memoryStream);
}
@@ -94,7 +109,7 @@ private TRead ReadObject(int len)
public void WriteObject(TWrite obj)
{
- var data = Serialize(obj);
+ byte[] data = Serialize(obj);
WriteLength(data.Length);
WriteObject(data);
Flush();
@@ -104,7 +119,7 @@ public void WriteObject(TWrite obj)
private byte[] Serialize(TWrite obj)
{
- using (var memoryStream = new MemoryStream())
+ using (MemoryStream memoryStream = new MemoryStream())
{
_binaryFormatter.Serialize(memoryStream, obj);
return memoryStream.ToArray();
@@ -113,7 +128,7 @@ private byte[] Serialize(TWrite obj)
private void WriteLength(int len)
{
- var lenbuf = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(len));
+ byte[] lenbuf = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(len));
_outStream.Write(lenbuf, 0, lenbuf.Length);
}
diff --git a/src/ObjectStream/ObjectStreamClient.cs b/src/ObjectStream/ObjectStreamClient.cs
index 06167a1..beb6c14 100644
--- a/src/ObjectStream/ObjectStreamClient.cs
+++ b/src/ObjectStream/ObjectStreamClient.cs
@@ -34,7 +34,7 @@ public ObjectStreamClient(Stream inStream, Stream outStream)
public void Start()
{
- var worker = new Worker();
+ Worker worker = new Worker();
worker.Error += OnError;
worker.DoWork(ListenSync);
}
@@ -42,13 +42,17 @@ public void Start()
public void PushMessage(TWrite message)
{
if (_connection != null)
+ {
_connection.PushMessage(message);
+ }
}
public void Stop()
{
if (_connection != null)
+ {
_connection.Close();
+ }
}
#region Private methods
@@ -65,7 +69,9 @@ private void ListenSync()
private void OnReceiveMessage(ObjectStreamConnection connection, TRead message)
{
if (Message != null)
+ {
Message(connection, message);
+ }
}
private void ConnectionOnError(ObjectStreamConnection connection, Exception exception)
@@ -76,7 +82,9 @@ private void ConnectionOnError(ObjectStreamConnection connection,
private void OnError(Exception exception)
{
if (Error != null)
+ {
Error(exception);
+ }
}
#endregion Private methods
diff --git a/src/ObjectStream/ObjectStreamConnection.cs b/src/ObjectStream/ObjectStreamConnection.cs
index f9eb44d..5aa6a72 100644
--- a/src/ObjectStream/ObjectStreamConnection.cs
+++ b/src/ObjectStream/ObjectStreamConnection.cs
@@ -26,11 +26,11 @@ internal ObjectStreamConnection(Stream inStream, Stream outStream)
public void Open()
{
- var readWorker = new Worker();
+ Worker readWorker = new Worker();
readWorker.Error += OnError;
readWorker.DoWork(ReadStream);
- var writeWorker = new Worker();
+ Worker writeWorker = new Worker();
writeWorker.Error += OnError;
writeWorker.DoWork(WriteStream);
}
@@ -53,16 +53,22 @@ private void CloseImpl()
private void OnError(Exception exception)
{
if (Error != null)
+ {
Error(this, exception);
+ }
}
private void ReadStream()
{
while (_streamWrapper.CanRead)
{
- var obj = _streamWrapper.ReadObject();
+ TRead obj = _streamWrapper.ReadObject();
ReceiveMessage?.Invoke(this, obj);
- if (obj != null) continue;
+ if (obj != null)
+ {
+ continue;
+ }
+
CloseImpl();
return;
}
@@ -74,7 +80,9 @@ private void WriteStream()
{
_writeSignal.WaitOne();
while (_writeQueue.Count > 0)
+ {
_streamWrapper.WriteObject(_writeQueue.Dequeue());
+ }
}
}
}
diff --git a/src/ObjectStream/Threading/Worker.cs b/src/ObjectStream/Threading/Worker.cs
index f052d87..b9f2e8d 100644
--- a/src/ObjectStream/Threading/Worker.cs
+++ b/src/ObjectStream/Threading/Worker.cs
@@ -19,7 +19,7 @@ public void DoWork(Action action)
private void DoWorkImpl(object oAction)
{
- var action = (Action)oAction;
+ Action action = (Action)oAction;
try
{
action();
@@ -33,7 +33,9 @@ private void DoWorkImpl(object oAction)
private void Fail(Exception exception)
{
if (Error != null)
+ {
Error(exception);
+ }
}
private void Callback(Action action)
diff --git a/src/Oxide.CSharp.csproj b/src/Oxide.CSharp.csproj
index 30bfaa0..c3144f6 100644
--- a/src/Oxide.CSharp.csproj
+++ b/src/Oxide.CSharp.csproj
@@ -1,31 +1,25 @@
+
2.0.0
Oxide.CSharp
Oxide and Contributors
+ (c) 2013-$([System.DateTime]::Now.Year) $(Authors)
C#/CSharp (.cs) plugin support for the Oxide modding framework
https://github.com/OxideMod/Oxide.CSharp
- https://github.com/OxideMod/Oxide.CSharp/blob/develop/LICENSE.md
- https://github.com/OxideMod/Oxide.CSharp
- https://avatars1.githubusercontent.com/u/10712027?s=64
- Copyright (c) 2014-$([System.DateTime]::Now.Year) $(Authors)
- api framework gaming modding plugins csharp c#
- net46;net45;net40;net35
- True
-
- C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client
- /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/2.0-api
- Oxide.Core.CSharp
+ icon.png
+ MIT
+ $(RepositoryUrl)
+ net35;net40;net45;net46
-
-
+
+ contentfiles;analyzers;build
+
+
diff --git a/src/PluginCompiler.cs b/src/PluginCompiler.cs
index 947e737..af1af09 100644
--- a/src/PluginCompiler.cs
+++ b/src/PluginCompiler.cs
@@ -31,8 +31,8 @@ public class PluginCompiler
public static void CheckCompilerBinary()
{
BinaryPath = null;
- var rootDirectory = Interface.Oxide.RootDirectory;
- var binaryPath = Path.Combine(rootDirectory, FileName);
+ string rootDirectory = Interface.Oxide.RootDirectory;
+ string binaryPath = Path.Combine(rootDirectory, FileName);
if (File.Exists(binaryPath))
{
@@ -57,7 +57,10 @@ public static void CheckCompilerBinary()
UpdateCheck(); // TODO: Only check once on server startup
try
{
- if (Syscall.access(binaryPath, AccessModes.X_OK) == 0) break;
+ if (Syscall.access(binaryPath, AccessModes.X_OK) == 0)
+ {
+ break;
+ }
}
catch (Exception ex)
{
@@ -82,12 +85,15 @@ public static void CheckCompilerBinary()
private void DependencyTrace()
{
- if (TraceRan || Environment.OSVersion.Platform != PlatformID.Unix) return;
+ if (TraceRan || Environment.OSVersion.Platform != PlatformID.Unix)
+ {
+ return;
+ }
try
{
Interface.Oxide.LogWarning($"Running dependency trace for {FileName}");
- var trace = new Process
+ Process trace = new Process
{
StartInfo =
{
@@ -125,15 +131,19 @@ private static void DownloadCompiler(WebResponse response, string remoteHash)
{
Interface.Oxide.LogInfo($"Downloading {FileName} for .cs (C#) plugin compilation");
- var stream = response.GetResponseStream();
- var fs = new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.None);
- var bufferSize = 10000;
- var buffer = new byte[bufferSize];
+ Stream stream = response.GetResponseStream();
+ FileStream fs = new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.None);
+ int bufferSize = 10000;
+ byte[] buffer = new byte[bufferSize];
while (true)
{
- var result = stream.Read(buffer, 0, bufferSize);
- if (result == -1 || result == 0) break;
+ int result = stream.Read(buffer, 0, bufferSize);
+ if (result == -1 || result == 0)
+ {
+ break;
+ }
+
fs.Write(buffer, 0, result);
}
fs.Flush();
@@ -147,7 +157,7 @@ private static void DownloadCompiler(WebResponse response, string remoteHash)
return;
}
- var localHash = File.Exists(BinaryPath) ? GetHash(BinaryPath, Algorithms.MD5) : "0";
+ string localHash = File.Exists(BinaryPath) ? GetHash(BinaryPath, Algorithms.MD5) : "0";
if (remoteHash != localHash)
{
Interface.Oxide.LogInfo($"Local hash did not match remote hash for {FileName}, attempting download again");
@@ -169,13 +179,17 @@ private static void UpdateCheck()
{
try
{
- var filePath = Path.Combine(Interface.Oxide.RootDirectory, FileName);
- var request = (HttpWebRequest)WebRequest.Create($"https://umod-01.nyc3.digitaloceanspaces.com/{FileName}");
- var response = (HttpWebResponse)request.GetResponse();
- var statusCode = (int)response.StatusCode;
- if (statusCode != 200) Interface.Oxide.LogWarning($"Status code from download location was not okay (code {statusCode})");
- var remoteHash = response.Headers[HttpResponseHeader.ETag].Trim('"');
- var localHash = File.Exists(filePath) ? GetHash(filePath, Algorithms.MD5) : "0";
+ string filePath = Path.Combine(Interface.Oxide.RootDirectory, FileName);
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"https://umod-01.nyc3.digitaloceanspaces.com/{FileName}");
+ HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ int statusCode = (int)response.StatusCode;
+ if (statusCode != 200)
+ {
+ Interface.Oxide.LogWarning($"Status code from download location was not okay (code {statusCode})");
+ }
+
+ string remoteHash = response.Headers[HttpResponseHeader.ETag].Trim('"');
+ string localHash = File.Exists(filePath) ? GetHash(filePath, Algorithms.MD5) : "0";
Interface.Oxide.LogInfo($"Latest compiler MD5: {remoteHash}");
Interface.Oxide.LogInfo($"Local compiler MD5: {localHash}");
if (remoteHash != localHash)
@@ -214,8 +228,8 @@ public PluginCompiler()
internal void Compile(CompilablePlugin[] plugins, Action callback)
{
- var id = lastId++;
- var compilation = new Compilation(id, callback, plugins);
+ int id = lastId++;
+ Compilation compilation = new Compilation(id, callback, plugins);
compilations[id] = compilation;
compilation.Prepare(() => EnqueueCompilation(compilation));
}
@@ -223,23 +237,36 @@ internal void Compile(CompilablePlugin[] plugins, Action callback)
public void Shutdown()
{
ready = false;
- var endedProcess = process;
- if (endedProcess != null) endedProcess.Exited -= OnProcessExited;
+ Process endedProcess = process;
+ if (endedProcess != null)
+ {
+ endedProcess.Exited -= OnProcessExited;
+ }
+
process = null;
- if (client == null) return;
+ if (client == null)
+ {
+ return;
+ }
client.Message -= OnMessage;
client.Error -= OnError;
client.PushMessage(new CompilerMessage { Type = CompilerMessageType.Exit });
client.Stop();
client = null;
- if (endedProcess == null) return;
+ if (endedProcess == null)
+ {
+ return;
+ }
ThreadPool.QueueUserWorkItem(_ =>
{
Thread.Sleep(5000);
// Calling Close can block up to 60 seconds on certain machines
- if (!endedProcess.HasExited) endedProcess.Close();
+ if (!endedProcess.HasExited)
+ {
+ endedProcess.Close();
+ }
});
}
@@ -259,20 +286,24 @@ private void EnqueueCompilation(Compilation compilation)
compilation.Started();
//Interface.Oxide.LogDebug("Compiling with references: {0}", compilation.references.Keys.ToSentence());
- var sourceFiles = compilation.plugins.SelectMany(plugin => plugin.IncludePaths).Distinct().Select(path => new CompilerFile(path)).ToList();
+ List sourceFiles = compilation.plugins.SelectMany(plugin => plugin.IncludePaths).Distinct().Select(path => new CompilerFile(path)).ToList();
sourceFiles.AddRange(compilation.plugins.Select(plugin => new CompilerFile($"{plugin.ScriptName}.cs", plugin.ScriptSource)));
//Interface.Oxide.LogDebug("Compiling files: {0}", sourceFiles.Select(f => f.Name).ToSentence());
- var data = new CompilerData
+ CompilerData data = new CompilerData
{
OutputFile = compilation.name,
SourceFiles = sourceFiles.ToArray(),
ReferenceFiles = compilation.references.Values.ToArray()
};
- var message = new CompilerMessage { Id = compilation.id, Data = data, Type = CompilerMessageType.Compile };
+ CompilerMessage message = new CompilerMessage { Id = compilation.id, Data = data, Type = CompilerMessageType.Compile };
if (ready)
+ {
client.PushMessage(message);
+ }
else
+ {
messageQueue.Enqueue(message);
+ }
}
private void OnMessage(ObjectStreamConnection connection, CompilerMessage message)
@@ -291,36 +322,44 @@ private void OnMessage(ObjectStreamConnection
switch (message.Type)
{
case CompilerMessageType.Assembly:
- var compilation = compilations[message.Id];
+ Compilation compilation = compilations[message.Id];
if (compilation == null)
{
Interface.Oxide.LogWarning("Compiler compiled an unknown assembly"); // TODO: Any way to clarify this?
return;
}
compilation.endedAt = Interface.Oxide.Now;
- var stdOutput = (string)message.ExtraData;
+ string stdOutput = (string)message.ExtraData;
if (stdOutput != null)
{
- foreach (var line in stdOutput.Split('\r', '\n'))
+ foreach (string line in stdOutput.Split('\r', '\n'))
{
- var match = fileErrorRegex.Match(line.Trim());
- for (var i = 1; i < match.Groups.Count; i++)
+ Match match = fileErrorRegex.Match(line.Trim());
+ for (int i = 1; i < match.Groups.Count; i++)
{
- var value = match.Groups[i].Value;
- if (value.Trim() == string.Empty) continue;
- var fileName = value.Basename();
- var scriptName = fileName.Substring(0, fileName.Length - 3);
- var compilablePlugin = compilation.plugins.SingleOrDefault(pl => pl.ScriptName == scriptName);
+ string value = match.Groups[i].Value;
+ if (value.Trim() == string.Empty)
+ {
+ continue;
+ }
+
+ string fileName = value.Basename();
+ string scriptName = fileName.Substring(0, fileName.Length - 3);
+ CompilablePlugin compilablePlugin = compilation.plugins.SingleOrDefault(pl => pl.ScriptName == scriptName);
if (compilablePlugin == null)
{
Interface.Oxide.LogError($"Unable to resolve script error to plugin: {line}");
continue;
}
- var missingRequirements = compilablePlugin.Requires.Where(name => !compilation.IncludesRequiredPlugin(name));
+ IEnumerable missingRequirements = compilablePlugin.Requires.Where(name => !compilation.IncludesRequiredPlugin(name));
if (missingRequirements.Any())
+ {
compilablePlugin.CompilerErrors = $"Missing dependencies: {missingRequirements.ToSentence()}";
+ }
else
+ {
compilablePlugin.CompilerErrors = line.Trim().Replace(Interface.Oxide.PluginDirectory + Path.DirectorySeparatorChar, string.Empty);
+ }
}
}
}
@@ -332,7 +371,10 @@ private void OnMessage(ObjectStreamConnection
Interface.Oxide.NextTick(() =>
{
idleTimer?.Destroy();
- if (AutoShutdown) idleTimer = Interface.Oxide.GetLibrary().Once(60, Shutdown);
+ if (AutoShutdown)
+ {
+ idleTimer = Interface.Oxide.GetLibrary().Once(60, Shutdown);
+ }
});
}
break;
@@ -357,7 +399,10 @@ private void OnMessage(ObjectStreamConnection
if (!ready)
{
ready = true;
- while (messageQueue.Count > 0) connection.PushMessage(messageQueue.Dequeue());
+ while (messageQueue.Count > 0)
+ {
+ connection.PushMessage(messageQueue.Dequeue());
+ }
}
break;
}
@@ -370,14 +415,21 @@ private bool CheckCompiler()
CheckCompilerBinary();
idleTimer?.Destroy();
- if (BinaryPath == null) return false;
- if (process != null && process.Handle != IntPtr.Zero && !process.HasExited) return true;
+ if (BinaryPath == null)
+ {
+ return false;
+ }
+
+ if (process != null && process.Handle != IntPtr.Zero && !process.HasExited)
+ {
+ return true;
+ }
SetCompilerVersion();
PurgeOldLogs();
Shutdown();
- var args = new[] { "/service", "/logPath:" + EscapePath(Interface.Oxide.LogDirectory) };
+ string[] args = new[] { "/service", "/logPath:" + EscapePath(Interface.Oxide.LogDirectory) };
try
{
process = new Process
@@ -418,14 +470,31 @@ private bool CheckCompiler()
process?.Dispose();
process = null;
Interface.Oxide.LogException($"Exception while starting compiler version {CompilerVersion}: ", ex);
- if (BinaryPath.Contains("'")) Interface.Oxide.LogWarning("Server directory path contains an apostrophe, compiler will not work until path is renamed");
- else if (Environment.OSVersion.Platform == PlatformID.Unix) Interface.Oxide.LogWarning("Compiler may not be set as executable; chmod +x or 0744/0755 required");
- if (ex.GetBaseException() != ex) Interface.Oxide.LogException("BaseException: ", ex.GetBaseException());
- var win32 = ex as Win32Exception;
- if (win32 != null) Interface.Oxide.LogError("Win32 NativeErrorCode: {0} ErrorCode: {1} HelpLink: {2}", win32.NativeErrorCode, win32.ErrorCode, win32.HelpLink);
+ if (BinaryPath.Contains("'"))
+ {
+ Interface.Oxide.LogWarning("Server directory path contains an apostrophe, compiler will not work until path is renamed");
+ }
+ else if (Environment.OSVersion.Platform == PlatformID.Unix)
+ {
+ Interface.Oxide.LogWarning("Compiler may not be set as executable; chmod +x or 0744/0755 required");
+ }
+
+ if (ex.GetBaseException() != ex)
+ {
+ Interface.Oxide.LogException("BaseException: ", ex.GetBaseException());
+ }
+
+ Win32Exception win32 = ex as Win32Exception;
+ if (win32 != null)
+ {
+ Interface.Oxide.LogError("Win32 NativeErrorCode: {0} ErrorCode: {1} HelpLink: {2}", win32.NativeErrorCode, win32.ErrorCode, win32.HelpLink);
+ }
}
- if (process == null) return false;
+ if (process == null)
+ {
+ return false;
+ }
client = new ObjectStreamClient(process.StandardOutput.BaseStream, process.StandardInput.BaseStream);
client.Message += OnMessage;
@@ -499,9 +568,13 @@ private void OnProcessExited(object sender, EventArgs eventArgs)
private void OnCompilerFailed(string reason)
{
- foreach (var compilation in compilations.Values)
+ foreach (Compilation compilation in compilations.Values)
{
- foreach (var plugin in compilation.plugins) plugin.CompilerErrors = reason;
+ foreach (CompilablePlugin plugin in compilation.plugins)
+ {
+ plugin.CompilerErrors = reason;
+ }
+
compilation.Completed();
}
compilations.Clear();
@@ -511,12 +584,15 @@ private static void PurgeOldLogs()
{
try
{
- var filePaths = Directory.GetFiles(Interface.Oxide.LogDirectory, "*.txt").Where(f =>
+ IEnumerable filePaths = Directory.GetFiles(Interface.Oxide.LogDirectory, "*.txt").Where(f =>
{
- var fileName = Path.GetFileName(f);
+ string fileName = Path.GetFileName(f);
return fileName != null && fileName.StartsWith("compiler_");
});
- foreach (var filePath in filePaths) File.Delete(filePath);
+ foreach (string filePath in filePaths)
+ {
+ File.Delete(filePath);
+ }
}
catch (Exception)
{
@@ -526,7 +602,10 @@ private static void PurgeOldLogs()
private static string EscapePath(string path)
{
- if (string.IsNullOrEmpty(path)) return "\"\"";
+ if (string.IsNullOrEmpty(path))
+ {
+ return "\"\"";
+ }
path = Regex.Replace(path, @"(\\*)" + "\"", @"$1\$0");
path = Regex.Replace(path, @"^(.*\s.*?)(\\*)$", "\"$1$2$2\"");
@@ -545,9 +624,9 @@ private static class Algorithms
private static string GetHash(string filePath, HashAlgorithm algorithm)
{
- using (var stream = new BufferedStream(File.OpenRead(filePath), 100000))
+ using (BufferedStream stream = new BufferedStream(File.OpenRead(filePath), 100000))
{
- var hash = algorithm.ComputeHash(stream);
+ byte[] hash = algorithm.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", string.Empty).ToLower();
}
}
diff --git a/src/Utility.cs b/src/Utility.cs
index 80ce3de..51706f9 100644
--- a/src/Utility.cs
+++ b/src/Utility.cs
@@ -22,20 +22,29 @@ public TValue this[TKey key]
{
get
{
- TValue value;
- if (TryGetValue(key, out value))
+ if (TryGetValue(key, out TValue value))
+ {
return value;
+ }
+
if (typeof(TValue).IsValueType)
+ {
return (TValue)Activator.CreateInstance(typeof(TValue));
+ }
+
return default(TValue);
}
set
{
if (value == null)
+ {
dictionary.Remove(key);
+ }
else
+ {
dictionary[key] = value;
+ }
}
}
@@ -45,14 +54,23 @@ public TValue this[TKey key]
public bool IsReadOnly => dictionary.IsReadOnly;
public IEnumerator> GetEnumerator() => dictionary.GetEnumerator();
+
public bool ContainsKey(TKey key) => dictionary.ContainsKey(key);
+
public bool Contains(KeyValuePair item) => dictionary.Contains(item);
+
public void CopyTo(KeyValuePair[] array, int index) => dictionary.CopyTo(array, index);
+
public bool TryGetValue(TKey key, out TValue value) => dictionary.TryGetValue(key, out value);
+
public void Add(TKey key, TValue value) => dictionary.Add(key, value);
+
public void Add(KeyValuePair item) => dictionary.Add(item);
+
public bool Remove(TKey key) => dictionary.Remove(key);
+
public bool Remove(KeyValuePair item) => dictionary.Remove(item);
+
public void Clear() => dictionary.Clear();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();