private void Initialize() { BootstrapLog.Info("Initializing."); _bootstrapMonoCecil.Initialize(); _bootstrapInterface.WrapReflection(); try { var resolutionHandler = Delegate.CreateDelegate(typeof(Func <AssemblyLoadContext, AssemblyName, Assembly>), this, "ResolveBootstrappedAssembly"); _bootstrapInterface.BindGameAssemblyManager_LoadContext_Resolving(resolutionHandler); } catch (Exception e) { Log.Error(e, e.Message + "\n" + e.StackTrace); } }
private Assembly ResolveBootstrappedAssembly(AssemblyLoadContext loadContext, AssemblyName name) { BootstrapLog.Info($"Attempting to resolve assembly '{name.FullName}'"); foreach (var assembly in _bootstrapInterface.GetSandboxAssemblies()) { if (name.Name == assembly.GetName().Name) { BootstrapLog.Info($"Resolved with '{assembly.FullName}'"); return(assembly); } } BootstrapLog.Error($"Could not resolve assembly '{name.FullName}'."); return(null); }
internal bool Initialize() { BootstrapLog.Info("Initializing Sandbox.Bootstrap.MonoCecil.dll"); AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { if (_sandboxMonoCecilAssembly == null) { return(null); } if (args.RequestingAssembly !.FullName == _sandboxMonoCecilAssembly.FullName) { var dnlib = FileSystem.Mounted.ReadAllBytes("bootstrap_monocecil/dnlib.dll"); return(Assembly.Load(dnlib.ToArray())); } return(null); }; try { var bootstrap = FileSystem.Mounted.ReadAllBytes("bootstrap_monocecil/Sandbox.Bootstrap.MonoCecil.dll"); _sandboxMonoCecilAssembly = Assembly.Load(bootstrap.ToArray()); _monocecil_ModifyAssemblyReference = _sandboxMonoCecilAssembly.GetType("Sandbox.Bootstrap.MonoCecil.AssemblyReferenceEditor") ?.GetMethod("ModifyAssemblyReference", BindingFlags.Public | BindingFlags.Static) ?.CreateDelegate <Func <Stream, string[], AssemblyName[], Stream> >(null); if (_sandboxMonoCecilAssembly == null || _monocecil_ModifyAssemblyReference == null) { BootstrapLog.Error("Failed to bind to Sandbox.Bootstrap.MonoCecil.AssemblyReferenceEditor. Make sure your Sandbox.Bootstrap install is correct."); return(false); } BootstrapLog.Info("Succesfully loaded, ready to modify assembly references."); return(true); } catch (Exception ex) { BootstrapLog.Error(ex, "An exception has occured while trying to bind to Sandbox.Bootstrap.MonoCecil.AssemblyReferenceEditor. Make sure your Sandbox.Bootstrap install is correct."); return(false); } }
public Assembly Boot(BootstrappedAddonBuilder bootstrapBuilder) { if (bootstrapBuilder == null) { throw new ArgumentNullException(nameof(bootstrapBuilder)); } BootstrapLog.Info($"Loading assembly at '{bootstrapBuilder.AssemblyName}'"); bootstrapBuilder.AssertValid(); // Get the name of the assembly we're trying to load. var relativePath = $"bootstrapped/{bootstrapBuilder.AssemblyName}/{bootstrapBuilder.AssemblyName}.dll"; var absolutePath = FileSystem.Mounted.GetFullPath(relativePath); if (absolutePath == null) { BootstrapLog.Error($"Could not find assembly '{relativePath}'"); return(null); } AssemblyName name; try { name = AssemblyName.GetAssemblyName(absolutePath); BootstrapLog.Info($"Found assembly '{name.FullName}' at '{relativePath}', attempting to load."); } catch (Exception e) { BootstrapLog.Error(e, $"Failed to load assembly '{bootstrapBuilder.AssemblyName}'."); return(null); } BootstrapLog.Info($"Valid filesystem: {FileSystem.Mounted.IsValid}"); Assembly asm; // Now we load the assembly. try { using var dllFile = FileSystem.Mounted.OpenRead(relativePath); // Before loading, grab all of the dynamic addons currently loaded, and ask Sandbox.Bootstrap.MonoCecil to modify them. BootstrapLog.Info("[Sandbox.Bootstrap.MonoCecil] Attempting to override references."); var oldReferences = new List <string>(); var newReferences = new List <AssemblyName>(); foreach (var sboxAssembly in _bootstrapInterface.GetSandboxAssemblies()) { if (sboxAssembly != null) { var asmName = sboxAssembly.GetName(); var split = asmName.Name !.Split('.'); if (split.Length > 1 && split[0] == "Dynamic") { oldReferences.Add(split[1]); newReferences.Add(asmName); } } } var output = _bootstrapMonoCecil.ModifyAssemblyReference(dllFile, oldReferences.ToArray(), newReferences.ToArray()); asm = _bootstrapInterface.GameAssemblyManager_LoadContext_LoadFromStream(output); } catch (Exception e) { BootstrapLog.Error(e, $"Failed to load assembly '{name.FullName}' at '{bootstrapBuilder.AssemblyName}'"); return(null); } // Woohoo we did it. BootstrapLog.Info($"Successfully loaded assembly '{asm.FullName}'."); bootstrapBuilder.OnAssemblyLoaded?.Invoke(asm); return(asm); }
/// <summary> /// Setup all of the required Reflection to interface with Sandbox. /// </summary> /// <exception cref="InvalidOperationException"> Thrown if any of the required Reflection calls fail. If this occurs, Sandbox likely got updated. Create an issue on our github repo. </exception> internal void WrapReflection() { if (_wrapped) { return; } _wrapped = true; BootstrapLog.Info("Wrapping Sandbox internals using Reflection."); // Retrieve Sandbox's context interface from the Global class. _contextInterface = typeof(Global).GetProperty("GameInterface", BindingFlags.Static | BindingFlags.NonPublic) ?.GetValue(null, null); if (_contextInterface == null) { BootstrapLog.Error("Bootstrapper is out of date! Could not retrieve Global.GameInterface!"); return; } // Create a delegate for the ContextInterface.OnNewAssembly method. var original = Type.GetType($"Sandbox.ServerInterface, {typeof(Global).Assembly.FullName}") ?.GetMethod("OnNewAssembly", BindingFlags.NonPublic | BindingFlags.Instance); if (original == null) { BootstrapLog.Error("Bootstrapper is out of date! Could not bind to Sandbox.ContextInterface.OnNewAssembly(Assembly, Assembly)!"); return; } _onNewAssembly = original.CreateDelegate <Action <Assembly, Assembly> >(_contextInterface); // Retrieve Sandbox's AssemblyLibrary _assemblyLibrary_All = Type.GetType($"Sandbox.AssemblyLibrary, {typeof(Global).Assembly.FullName}") ?.GetField("All", BindingFlags.Static | BindingFlags.Public); if (_assemblyLibrary_All == null) { BootstrapLog.Error("Bootstrapper is out of date! Could not bind to Sandbox.AssemblyLibrary.All!"); return; } // Retrieve Sandbox's AssemblyLibrary _assemblyWrapper_Assembly = Type.GetType($"Sandbox.AssemblyWrapper, {typeof(Global).Assembly.FullName}") ?.GetField("Assembly", BindingFlags.Public | BindingFlags.Instance); if (_assemblyWrapper_Assembly == null) { BootstrapLog.Error("Bootstrapper is out of date! Could not bind to Sandbox.AssemblyWrapper.Assembly!"); return; } _gameAssemblyManager_OnAssembly = Type.GetType($"Sandbox.GameAssemblyManager, {typeof(Global).Assembly.FullName}") ?.GetMethod("OnAssembly", BindingFlags.NonPublic | BindingFlags.Static) ?.CreateDelegate <Action <string, Stream, Stream> >(); if (_gameAssemblyManager_OnAssembly == null) { BootstrapLog.Error("Bootstrapper is out of date! Could not bind to Sandbox.GameAssemblyManager.OnAssembly!"); return; } _gameAssemblyManager_LoadContext = Type.GetType($"Sandbox.GameAssemblyManager, {typeof(Global).Assembly.FullName}") ?.GetField("LoadContext", BindingFlags.NonPublic | BindingFlags.Static); if (_gameAssemblyManager_LoadContext == null) { BootstrapLog.Error("Bootstrapper is out of date! Could not bind to Sandbox.GameAssemblyManager.LoadContext!"); return; } _gameAssemblyManager_LoadContext_Resolving = typeof(AssemblyLoadContext).GetEvent("Resolving", BindingFlags.Instance | BindingFlags.Public); if (_gameAssemblyManager_LoadContext_Resolving == null) { BootstrapLog.Error("Bootstrapper is out of date! Could not bind to Sandbox.GameAssemblyManager.LoadContext.Resolving!"); return; } try { _gameAssemblyManager_LoadContext_LoadFromStream = typeof(AssemblyLoadContext) .GetMethod("LoadFromStream", new[] { typeof(Stream) }) ?.CreateDelegate <Func <Stream, Assembly> >(_gameAssemblyManager_LoadContext?.GetValue(null)); if (_gameAssemblyManager_LoadContext_LoadFromStream == null) { BootstrapLog.Error("Bootstrapper is out of date! Could not bind to Sandbox.GameAssemblyManager.LoadContext.LoadFromStream!"); return; } } catch (Exception e) { Log.Info($"{e.Message}\n{e.StackTrace}"); } }