/// <summary> /// Creates a list of TDefinitions, loading defintitions found in Categories and Includes. /// </summary> /// <typeparam name="TDefinition"></typeparam> /// <param name="sourceDefinitions"></param> /// <returns></returns> public static List <TDefinition> Flatten <TDefinition>(List <DefinitionBase> sourceDefinitions) where TDefinition : DefinitionBase { var result = new List <TDefinition>(sourceDefinitions.Count); foreach (var baseDef in sourceDefinitions) { var def = baseDef as TDefinition; if (def != null) { result.Add(def); } else if (baseDef is CategoryDefinition) { var category = (CategoryDefinition)baseDef; foreach (var kvp in category.DefinitionIncludes) { result.AddRange(DefinitionInclude.Flatten <TDefinition>(kvp.Value)); } } } return(result); }
/// <summary> /// Loads in json definition files, and attempts to compile and link to any related scripts. /// </summary> protected virtual void LoadDefinitions() { //CustomNpcsPlugin.Instance.LogPrint("Using new definition loading, include paths aren't 100% reliable yet!",TraceLevel.Warning); var include = DefinitionInclude.Load <TCustomType>(ConfigPath); Definitions = DefinitionInclude.Flatten <TCustomType>(include); var rootResult = new ValidationResult(ConfigPath); rootResult.Source = ConfigPath; foreach (var def in Definitions) { var name = ""; var result = def.Validate(); if (!string.IsNullOrWhiteSpace(def.Name)) { name = $" - '{def.Name}'"; } //result.Source = $"{def.FilePath}[{def.LineNumber},{def.LinePosition}]{name}"; //CustomNpcsPlugin.Instance.LogPrint(result); rootResult.Children.Add(result); } CustomNpcsPlugin.Instance.LogPrint(rootResult); //Definitions = DefinitionLoader.LoadFromFile<TCustomType>(ConfigPath); CustomNpcsPlugin.Instance.LogPrint("Compiling scripts...", TraceLevel.Info); //get script files paths var booScripts = Definitions.Where(d => !string.IsNullOrWhiteSpace(d.ScriptPath)) .Select(d => Path.Combine(BasePath, d.ScriptPath)) .ToList(); var newModuleManager = new BooModuleManager(CustomNpcsPlugin.Instance, ScriptHelpers.GetReferences(), ScriptHelpers.GetDefaultImports(), GetEnsuredMethodSignatures()); newModuleManager.AssemblyNamePrefix = AssemblyNamePrefix; foreach (var f in booScripts) { newModuleManager.Add(f); } Dictionary <string, CompilerContext> results = null; if (ModuleManager != null) { results = newModuleManager.IncrementalCompile(ModuleManager); } else { results = newModuleManager.Compile(); } ModuleManager = newModuleManager; var scriptedDefinitions = Definitions.Where(d => !string.IsNullOrWhiteSpace(d.ScriptPath)); foreach (var def in scriptedDefinitions) { var fileName = Path.Combine(BasePath, def.ScriptPath); //if newly compile assembly, examine the context, and try to link to the new assembly if (results.TryGetValue(fileName, out var context)) { var scriptAssembly = context.GeneratedAssembly; if (scriptAssembly != null) { var result = def.LinkToScriptAssembly(scriptAssembly); //if(!result) // // CustomNpcsPlugin.Instance.LogPrint($"Failed to link {kvp.Key}.", TraceLevel.Info); } } else { var scriptAssembly = ModuleManager[fileName]; if (scriptAssembly != null) { var result = def.LinkToScriptAssembly(scriptAssembly); //if(!result) // // CustomNpcsPlugin.Instance.LogPrint($"Failed to link {kvp.Key}.", TraceLevel.Info); } } } definitionMap = new Dictionary <string, TCustomType>(); foreach (var def in Definitions) { definitionMap.Add(def.Name.ToLowerInvariant(), def); } }
public static DefinitionInclude Load <TDefinition>(string filePath) where TDefinition : DefinitionBase { if (!File.Exists(filePath)) { throw new FileNotFoundException($"Unable to find file '{filePath}'.", filePath); } var result = new DefinitionInclude(); result.FilePath = filePath; var definitionType = typeof(TDefinition); var typeName = definitionType.Name; var json = File.ReadAllText(filePath); var array = JArray.Parse(json); var children = array.Children().Where(jt => jt.Type == JTokenType.Object); DefinitionBase baseDef = null; foreach (var child in children) { if (child["Category"] != null) { var category = child.ToObject <CategoryDefinition>(); //do category specific things... baseDef = category; } else { var def = child.ToObject <TDefinition>(); //do TDefinition specific things... baseDef = def; } //set file and line info var filePos = baseDef.FilePosition = new FilePosition(filePath); var lineInfo = child as IJsonLineInfo; if (lineInfo?.HasLineInfo() == true) { filePos.Line = lineInfo.LineNumber; filePos.Column = lineInfo.LinePosition; //Debug.Print($"{filePath} [{baseDef.LineNumber},{baseDef.LinePosition}] {baseDef.Name}"); Debug.Print($"{filePos} {baseDef.Name}"); } result.Add(baseDef); } //load includes //Debug.Print("Categories are currently disabled."); var categories = result.OfType <CategoryDefinition>(); foreach (var category in categories) { foreach (var inc in category.Includes) { var relativeIncludePath = Path.Combine(Path.GetDirectoryName(filePath), inc); var defInclude = DefinitionInclude.Load <TDefinition>(relativeIncludePath); category.DefinitionIncludes.Add(inc, defInclude); } } return(result); }