/// <summary> /// Updates all absolute path'd cache entries to use a relative path instead /// </summary> public void UpdateToRelativePaths() { var toRemove = new List <string>(); var toAdd = new Dictionary <string, CacheEntry>(); foreach (var path in CachedEntries.Keys) { if (Path.IsPathRooted(path)) { var relativePath = ModTek.GetRelativePath(path, ModTek.GameDirectory); toAdd[relativePath] = CachedEntries[path]; toRemove.Add(path); toAdd[relativePath].CachePath = ModTek.GetRelativePath(toAdd[relativePath].CachePath, ModTek.GameDirectory); foreach (var merge in toAdd[relativePath].Merges) { merge.Path = ModTek.GetRelativePath(merge.Path, ModTek.GameDirectory); } } } foreach (var addKVP in toAdd) { CachedEntries.Add(addKVP.Key, addKVP.Value); } foreach (var path in toRemove) { CachedEntries.Remove(path); } }
static void Postfix(VersionManifest __result) { ModTek.LogWithDate("VersionManifestUtilities_LoadDefaultManifest_Patch"); // add to the manifest here // TODO: these freaking kvp look so bad foreach (var entryKVP in ModTek.NewManifestEntries) { var id = entryKVP.Key; var newEntry = entryKVP.Value; if (newEntry.ShouldMergeJSON && __result.Contains(id, newEntry.Type)) { // read the manifest pointed entry and hash the contents DoJSONMerge.JSONHashes.Add(File.ReadAllText(__result.Get(id, newEntry.Type).FilePath).GetHashCode()); // The manifest already contains this information, so we need to queue it to be merged var partialJSON = File.ReadAllText(newEntry.Path); if (!DoJSONMerge.JSONMerges.ContainsKey(id)) { DoJSONMerge.JSONMerges.Add(id, new List <string>()); } ModTek.Log("\tAdding id {0} to JSONMerges", id); DoJSONMerge.JSONMerges[id].Add(partialJSON); } else { // This is a new definition or a replacement that doesn't get merged, so add or update the manifest ModTek.Log("\tAddOrUpdate({0}, {1}, {2}, {3}, {4}, {5})", id, newEntry.Path, newEntry.Type, DateTime.Now, newEntry.AssetBundleName, newEntry.AssetBundlePersistent); __result.AddOrUpdate(id, newEntry.Path, newEntry.Type, DateTime.Now, newEntry.AssetBundleName, newEntry.AssetBundlePersistent); } } }
public static void Execute(ref string json) { var copy_json = json; try { var oldJObj = JObject.Parse(copy_json); var id = ModTek.InferIDFromJObject(oldJObj); if (JSONMerges.ContainsKey(id)) { JSONMerges[id].ForEach((string json_patch) => { var patchJObj = JObject.Parse(json_patch); oldJObj.Merge(patchJObj); }); JSONMerges.Remove(id); } // Once we are here, we can commit to changing the json file json = oldJObj.ToString(); } catch (JsonReaderException e) { ModTek.Log(e.Message); ModTek.Log(e.StackTrace); ModTek.Log("Error encountered loading json, skipping any patches which would have been applied."); } }
public static void Postfix(string json, ref string __result) { // function has invalid json coming from file // and hopefully valid json (i.e. comments out) coming out from function if (DoJSONMerge.JSONHashes.Contains(json.GetHashCode())) { ModTek.LogWithDate("Hash hit so running JSON Merge"); DoJSONMerge.Execute(ref __result); } }
public static void Postfix(ApplicationConstants __instance) { RLog.M.TWL(0, "ApplicationConstants.FromJSON. PrewarmRequests:"); try { List <PrewarmRequest> prewarmRequests = new List <PrewarmRequest>(); prewarmRequests.AddRange(__instance.PrewarmRequests); HashSet <string> svgs = new HashSet <string>(); foreach (AmmoCategoryValue ammoCat in AmmoCategoryEnumeration.AmmoCategoryList) { if (ammoCat.isBuildinIcon() == false) { svgs.Add(ammoCat.Icon); } } foreach (WeaponCategoryValue weaponCat in WeaponCategoryEnumeration.WeaponCategoryList) { if (weaponCat.isBuildinIcon() == false) { svgs.Add(weaponCat.Icon); } } FieldInfo[] fields = typeof(UILookAndColorConstants).GetFields(); foreach (FieldInfo field in fields) { //RLog.M.WL(1, field.Name+":"+field.FieldType); if (field.FieldType != typeof(SVGAsset)) { continue; } string id = "UILookAndColorConstants." + field.Name; if (ModTek.isInSystemIcons(id)) { svgs.Add(id); } } foreach (string svg in svgs) { if (string.IsNullOrEmpty(svg) == false) { prewarmRequests.Add(new PrewarmRequest(BattleTechResourceType.SVGAsset, svg)); } ; } typeof(ApplicationConstants).GetProperty("PrewarmRequests", BindingFlags.Instance | BindingFlags.Public).GetSetMethod(true).Invoke(__instance, new object[] { prewarmRequests.ToArray() }); foreach (PrewarmRequest preq in __instance.PrewarmRequests) { RLog.M.WL(1, preq.ResourceType + ":" + preq.ResourceID); } } catch (Exception e) { RLog.M.TWL(0, e.ToString(), true); } }
/// <summary> /// Gets (from the cache) or creates (and adds to cache) a JSON merge /// </summary> /// <param name="absolutePath">The path to the original JSON file</param> /// <param name="mergePaths">A list of the paths to merged in JSON</param> /// <returns>A path to the cached JSON that contains the original JSON with the mod merges applied</returns> public string GetOrCreateCachedEntry(string absolutePath, List <string> mergePaths) { absolutePath = Path.GetFullPath(absolutePath); var relativePath = ModTek.GetRelativePath(absolutePath, ModTek.GameDirectory); Log(""); if (!CachedEntries.ContainsKey(relativePath) || !CachedEntries[relativePath].MatchesPaths(absolutePath, mergePaths)) { var cachedAbsolutePath = Path.GetFullPath(Path.Combine(ModTek.CacheDirectory, relativePath)); var cachedEntry = new CacheEntry(cachedAbsolutePath, absolutePath, mergePaths); if (cachedEntry.HasErrors) { return(null); } CachedEntries[relativePath] = cachedEntry; Log($"Merge performed: {Path.GetFileName(absolutePath)}"); } else { Log($"Cached merge: {Path.GetFileName(absolutePath)} ({File.GetLastWriteTime(CachedEntries[relativePath].CacheAbsolutePath).ToString("G")})"); } Log($"\t{relativePath}"); foreach (var contributingPath in mergePaths) { Log($"\t{ModTek.GetRelativePath(contributingPath, ModTek.ModsDirectory)}"); } Log(""); CachedEntries[relativePath].CacheHit = true; return(CachedEntries[relativePath].CacheAbsolutePath); }
internal bool MatchesPaths(string originalPath, List <string> mergePaths) { // must have an existing cached json if (!File.Exists(CacheAbsolutePath)) { return(false); } // must have the same original file if (File.GetLastWriteTimeUtc(originalPath) != OriginalTime) { return(false); } // must match number of merges if (mergePaths.Count != Merges.Count) { return(false); } // if all paths match with write times, we match for (var index = 0; index < mergePaths.Count; index++) { var mergeAbsolutePath = mergePaths[index]; var mergeTime = File.GetLastWriteTimeUtc(mergeAbsolutePath); var cachedMergeAboslutePath = ModTek.ResolvePath(Merges[index].Path, ModTek.GameDirectory); var cachedMergeTime = Merges[index].Time; if (mergeAbsolutePath != cachedMergeAboslutePath || mergeTime != cachedMergeTime) { return(false); } } return(true); }
public CacheEntry(string cacheAbsolutePath, string originalAbsolutePath, List <string> mergePaths) { _cacheAbsolutePath = cacheAbsolutePath; CachePath = ModTek.GetRelativePath(cacheAbsolutePath, ModTek.GameDirectory); ContainingDirectory = Path.GetDirectoryName(cacheAbsolutePath); OriginalTime = File.GetLastWriteTimeUtc(originalAbsolutePath); if (string.IsNullOrEmpty(ContainingDirectory)) { HasErrors = true; return; } // get the parent JSON JObject parentJObj; try { parentJObj = ModTek.ParseGameJSONFile(originalAbsolutePath); } catch (Exception e) { Log($"\tParent JSON at path {originalAbsolutePath} has errors preventing any merges!"); Log($"\t\t{e.Message}"); HasErrors = true; return; } foreach (var mergePath in mergePaths) { Merges.Add(new PathTimeTuple(ModTek.GetRelativePath(mergePath, ModTek.GameDirectory), File.GetLastWriteTimeUtc(mergePath))); } Directory.CreateDirectory(ContainingDirectory); using (var writer = File.CreateText(cacheAbsolutePath)) { // merge all of the merges foreach (var mergePath in mergePaths) { JObject mergeJObj; try { mergeJObj = ModTek.ParseGameJSONFile(mergePath); } catch (Exception e) { Log($"\tMod merge JSON at path {originalAbsolutePath} has errors preventing any merges!"); Log($"\t\t{e.Message}"); continue; } if (AdvancedJSONMerger.IsAdvancedJSONMerge(mergeJObj)) { try { AdvancedJSONMerger.ProcessInstructionsJObject(parentJObj, mergeJObj); continue; } catch (Exception e) { Log($"\tMod advanced merge JSON at path {mergePath} has errors preventing advanced json merges!"); Log($"\t\t{e.Message}"); } } // assume standard merging parentJObj.Merge(mergeJObj, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Replace }); } // write the merged onto file to disk var jsonWriter = new JsonTextWriter(writer) { Formatting = Formatting.Indented }; parentJObj.WriteTo(jsonWriter); jsonWriter.Close(); } }
/// <summary> /// Checks to see if this ModDef should load, providing a reason if shouldn't load /// </summary> public bool ShouldTryLoad(List <string> alreadyTryLoadMods, out string reason) { if (!Enabled) { reason = "it is disabled"; IgnoreLoadFailure = true; return(false); } if (alreadyTryLoadMods.Contains(Name)) { reason = $"ModTek already loaded with the same name. Skipping load from {ModTek.GetRelativePath(ModTek.ModsDirectory, Directory)}."; return(false); } // check game version vs. specific version or against min/max if (!string.IsNullOrEmpty(BattleTechVersion) && !VersionInfo.ProductVersion.StartsWith(BattleTechVersion)) { reason = $"it specifies a game version and this isn't it ({BattleTechVersion} vs. game {VersionInfo.ProductVersion})"; return(false); } var btgVersion = new Version(VersionInfo.ProductVersion); if (!string.IsNullOrEmpty(BattleTechVersionMin) && btgVersion < new Version(BattleTechVersionMin)) { reason = $"it doesn't match the min version set in the mod.json ({BattleTechVersionMin} vs. game {VersionInfo.ProductVersion})"; return(false); } if (!string.IsNullOrEmpty(BattleTechVersionMax) && btgVersion > new Version(BattleTechVersionMax)) { reason = $"it doesn't match the max version set in the mod.json ({BattleTechVersionMax} vs. game {VersionInfo.ProductVersion})"; return(false); } reason = ""; return(true); }
public static void Prefix() { ModTek.LoadMods(); }
public CacheEntry(string path, string originalPath, List <string> mergePaths) { CachePath = path; ContainingDirectory = Path.GetDirectoryName(path); OriginalPath = originalPath; OriginalTime = File.GetLastWriteTimeUtc(originalPath); if (string.IsNullOrEmpty(ContainingDirectory)) { HasErrors = true; return; } // get the parent JSON JObject parentJObj; try { parentJObj = ModTek.ParseGameJSON(File.ReadAllText(originalPath)); } catch (Exception e) { Log($"\tParent JSON at path {originalPath} has errors preventing any merges!"); Log($"\t\t{e.Message}"); HasErrors = true; return; } foreach (var mergePath in mergePaths) { Merges.Add(new PathTimeTuple(mergePath, File.GetLastWriteTimeUtc(mergePath))); } Directory.CreateDirectory(ContainingDirectory); using (var writer = File.CreateText(path)) { // merge all of the merges foreach (var mergePath in mergePaths) { JObject mergeJObj; try { mergeJObj = ModTek.ParseGameJSON(File.ReadAllText(mergePath)); } catch (Exception e) { Log($"\tMod merge JSON at path {originalPath} has errors preventing any merges!"); Log($"\t\t{e.Message}"); continue; } parentJObj.Merge(mergeJObj, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Replace }); } // write the merged onto file to disk var jsonWriter = new JsonTextWriter(writer) { Formatting = Formatting.Indented }; parentJObj.WriteTo(jsonWriter); jsonWriter.Close(); } }
public static string GetTargetFile(string modEntryPath) { var merge = ModTek.ParseGameJSONFile(modEntryPath); return(merge["TargetFile"].ToString()); }
public static void Postfix(VersionManifest __result) { ModTek.TryAddToVersionManifest(__result); }
public bool HasCachedEntry(string originalPath, List <string> mergePaths) { var relativePath = ModTek.GetRelativePath(originalPath, ModTek.GameDirectory); return(CachedEntries.ContainsKey(relativePath) && CachedEntries[relativePath].MatchesPaths(originalPath, mergePaths)); }
public static void Postfix(VersionManifest __result) { ModTek.AddModEntries(__result); }
public static string GetTargetID(string modEntryPath) { var merge = ModTek.ParseGameJSONFile(modEntryPath); return(merge[nameof(MergeFile.TargetID)].ToString()); }
public static void Postfix(string json, ref string __result) { // function has invalid json coming from file // and hopefully valid json (i.e. comments out) coming out from function ModTek.TryMergeJsonInto(json, ref __result); }