internal static void RunActions(ModEntry mod, string phase) { try { phase = phase.ToLowerInvariant(); var all = mod.Metadata.Actions; if (!QuickScanActions(all, phase)) { return; // TODO: move to ModScanner instead of rescanning every phase. } var log = mod.Log(); log.Verbo("Scanning {0} actions", all.Length); var actions = FilterActions(all, phase, out int defaultCount); if (actions == null) { return; } if (!InitActionHandlers()) { return; } log.Info("Running {0} actions ({1} defaults merged)", actions.Count, defaultCount); var modPrefix = mod.PrefixFilter; foreach (var dll in ActionHandlers) { var handler = ActionMods[dll]; if (handler != mod) { handler.Log().Filters.Add(modPrefix); } } foreach (var act in actions) { foreach (var dll in ActionHandlers) { var result = RunActionHandler(mod, dll, act); if (result is Exception ex && AbortOnError(log, act, ex)) { return; } } } foreach (var dll in ActionHandlers) { ActionMods[dll].Log().Filters.Remove(modPrefix); } } catch (Exception ex) { mod.Log().Error(ex); } }
public static Assembly LoadDll(ModEntry mod, string path) { try { if (mod.ModAssemblies != null) { foreach (var a in mod.ModAssemblies) { if (!a.IsDynamic && a.Location == path) { return(a); } } } /*if ( ! Tools.IsSafePath( path ) ) { // TODO: Make auto-scanned dll use relative path * mod.Log().Error( "Invalid or unsafe path: {0}", path ); * return null; * }*/ mod.Log().Info("Loading {0}", path); var asm = Assembly.LoadFrom(path); if (asm == null) { return(null); } if (mod.ModAssemblies == null) { mod.ModAssemblies = new List <Assembly>(); } if (!mod.ModAssemblies.Contains(asm)) { mod.ModAssemblies.Add(asm); } return(asm); } catch (Exception ex) { mod.Error(ex); return(null); } }
public static Assembly LoadDll(ModEntry mod, string path) { try { if (mod.ModAssemblies != null) { foreach (var a in mod.ModAssemblies) { if (!a.IsDynamic && a.Location == path) { return(a); } } } mod.Log().Info("Loading {0}", path); var asm = Assembly.LoadFrom(path); if (asm == null) { return(null); } if (mod.ModAssemblies == null) { mod.ModAssemblies = new List <Assembly>(); } if (!mod.ModAssemblies.Contains(asm)) { mod.ModAssemblies.Add(asm); } return(asm); } catch (Exception ex) { mod.Error(ex); return(null); } }
internal static ActionDef[] Resolve(ModEntry mod, ActionDef[] list) { try { ActionDef defValues = null; return(PreprocessActions(mod, list, ref defValues, 0)); } catch (Exception ex) { mod.Log().Error(ex); return(new ActionDef[0]); } }
internal static void RunActions(ModEntry mod, string phase) { try { var actions = FilterActions(mod.Metadata.Actions, phase.ToLowerInvariant()); var log = mod.Log(); log.Verbo("Running {0} actions", actions.Length); if (!InitActionHandlers()) { return; } var modPrefix = mod.PrefixFilter; foreach (var dll in ActionHandlers) { var handler = ActionMods[dll]; if (handler != mod) { handler.Log().Filters.Add(modPrefix); } } foreach (var act in actions) { foreach (var dll in ActionHandlers) { var result = RunActionHandler(mod, dll, act); if (result is Exception ex) { return; } } } foreach (var dll in ActionHandlers) { ActionMods[dll].Log().Filters.Remove(modPrefix); } } catch (Exception ex) { mod.Log().Error(ex); } }
private static void DisableAndRemoveMod(ModEntry mod, string reason, string log, params object[] augs) { lock ( mod ) { if (mod.Disabled) { return; } mod.Log().Info("Mod Disabled: " + log, augs); mod.Disabled = true; mod.AddNotice(TraceEventType.Error, reason, augs); EnabledMods.Remove(mod); ResolveModAgain = true; } }
private static object RunActionHandler(ModEntry mod, DllMeta dll, ActionDef act) { try { var lib = ModPhases.LoadDll(mod, dll.Path); if (lib == null) { return(false); } var handler = ActionMods[dll]; object GetParamValue(ParameterInfo pi) => ParamValue(act, pi, mod, handler); object result; foreach (var type in dll.Methods["ActionMod"]) { result = ModPhases.CallInit(mod, lib, type, "ActionMod", GetParamValue); if (result is bool success) { if (success) { return(true); } } else if (result is Exception ex) { LogActionError(handler.Log(), act, ex); if (InList(act.GetText("onerror"), "continue")) { continue; } if (InList(act.GetText("onerror"), "skip")) { return(null); } mod.Log().Info("Aborting Actions. Set OnError to \"Log,Continue\" or \"Log,Skip\" to ignore the error."); return(ex); } else if (result != null) { handler.Log().Error("Unexpected ActionMod result: {0}", result.GetType()); } } return(null); } catch (Exception ex) { mod.Error(ex); return(null); } }
private static ActionDef[] LoadInclude(ModEntry mod, string path, ref ActionDef defValues, int level) { if (!IsSafePath(path)) { mod.Log().Error("Invalid or unsafe path: {0}", path); return(new ActionDef[0]); } if (level > 9) { throw new ApplicationException("Action includes too deep: " + path); } // todo: refactor mod path var actions = Json.Parse <ActionDef[]>(ReadText(Path.Combine(Path.GetDirectoryName(mod.Path), path))); ModMeta.NormDictArray(ref actions); try { return(PreprocessActions(mod, actions, ref defValues, level)); } catch (ApplicationException ex) { throw new ApplicationException("Error when including " + path, ex); } }
public static object CallInit(ModEntry mod, Assembly dll, string typeName, string methodName, Func <ParameterInfo, object> paramGetter) { try { Logger log = mod.Log(); var type = dll.GetType(typeName); if (type == null) { log.Error("Cannot find type {1} in {0}", dll.Location, typeName); return(null); } var func = type.GetMethods(ModScanner.INIT_METHOD_FLAGS)?.FirstOrDefault(e => e.Name.Equals(methodName)); if (func == null) { log.Error("Cannot find {1}.{2} in {0}", dll.Location, typeName, methodName); return(null); } var args = func.GetParameters().Select(paramGetter); Func <string> argTxt = () => string.Join(", ", args.Select(e => e?.GetType()?.Name ?? "null")); log.Log(methodName == "ActionMod" ? SourceLevels.Verbose : SourceLevels.Information, "Calling {1}.{2}({3}) in {0}", dll.Location, typeName, methodName, argTxt); object target = null; if (!func.IsStatic) { lock ( ModInstances ) { if (!ModInstances.TryGetValue(type, out WeakReference <object> wref) || !wref.TryGetTarget(out target)) { ModInstances[type] = new WeakReference <object>(target = Activator.CreateInstance(type)); } } } var result = func.Invoke(target, args.ToArray()); log.Trace("Done calling {1}.{2}", typeName, methodName); return(result); } catch (Exception ex) { return(ex); } }