private object ConvertData(ModPackageExtended sourceModPack, ModPackageExtended destModPack, object data) { var type = data.GetType(); switch (data) { case null: case string _: case ValueType _: return(data); case PageableResource resource: return(ConvertPageableResource(sourceModPack, destModPack, resource)); case TagStructure structure: return(ConvertStructure(sourceModPack, destModPack, structure)); case IList collection: return(ConvertCollection(sourceModPack, destModPack, collection)); case CachedTagInstance tag: return(ConvertCachedTagInstance(sourceModPack, destModPack, tag)); } return(data); }
public void ConvertScriptExpressionData(ModPackageExtended modPack, HsSyntaxNode expr) { if (expr.Flags == HsSyntaxNodeFlags.Expression) { switch (expr.ValueType.HaloOnline) { case HsType.HaloOnlineValue.Sound: case HsType.HaloOnlineValue.Effect: case HsType.HaloOnlineValue.Damage: case HsType.HaloOnlineValue.LoopingSound: case HsType.HaloOnlineValue.AnimationGraph: case HsType.HaloOnlineValue.DamageEffect: case HsType.HaloOnlineValue.ObjectDefinition: case HsType.HaloOnlineValue.Bitmap: case HsType.HaloOnlineValue.Shader: case HsType.HaloOnlineValue.RenderModel: case HsType.HaloOnlineValue.StructureDefinition: case HsType.HaloOnlineValue.LightmapDefinition: case HsType.HaloOnlineValue.CinematicDefinition: case HsType.HaloOnlineValue.CinematicSceneDefinition: case HsType.HaloOnlineValue.BinkDefinition: case HsType.HaloOnlineValue.AnyTag: case HsType.HaloOnlineValue.AnyTagNotResolving: ConvertScriptTagReferenceExpressionData(modPack, expr); return; default: break; } } }
private Scenario ConvertScenario(ModPackageExtended modPack, Scenario scnr) { foreach (var expr in scnr.ScriptExpressions) { ConvertScriptExpression(modPack, expr); } return(scnr); }
public override object Execute(List <string> args) { if (args.Count < 1 || args.Count > 2) { return(false); } string sourcePackagePath; string destPackagePath; if (args.Count == 1) { sourcePackagePath = args[0]; destPackagePath = sourcePackagePath; } else { sourcePackagePath = args[0]; destPackagePath = args[1]; } if (!File.Exists(sourcePackagePath)) { Console.WriteLine("Source package not found!"); return(false); } var sourcePackage = new ModPackageSimplified(); sourcePackage.Load(new FileInfo(sourcePackagePath)); var destPackage = new ModPackageExtended(); var metadata = destPackage.Metadata; metadata.Author = sourcePackage.Metadata.Author; metadata.Description = sourcePackage.Metadata.Description; metadata.Name = sourcePackage.Metadata.Name; metadata.BuildDateLow = (int)DateTime.Now.ToFileTime() & 0x7FFFFFFF; metadata.BuildDateHigh = (int)((DateTime.Now.ToFileTime() & 0x7FFFFFFF00000000) >> 32); destPackage.Tags = sourcePackage.Tags; destPackage.TagsStream = sourcePackage.TagsStream; destPackage.TagNames = sourcePackage.TagNames; destPackage.Resources = sourcePackage.Resources; destPackage.ResourcesStream = sourcePackage.ResourcesStream; destPackage.MapFileStreams = sourcePackage.CacheStreams; destPackage.DetermineMapFlags(); destPackage.Save(new FileInfo(destPackagePath)); Console.WriteLine("Done!"); return(true); }
private PageableResource ConvertPageableResource(ModPackageExtended sourceModPack, ModPackageExtended destModPack, PageableResource resource) { if (resource.Page.Index == -1) { return(resource); } var resourceData = sourceModPack.Resources.ExtractRaw(sourceModPack.ResourcesStream, resource.Page.Index, resource.Page.CompressedBlockSize); resource.Page.Index = destModPack.Resources.Add(destModPack.ResourcesStream, resourceData, out resource.Page.CompressedBlockSize); return(resource); }
private CachedTagInstance ConvertCachedTagInstance(ModPackageExtended modPack, CachedTagInstance modTag) { // Determine if tag requires conversion if (modPack.Tags.Index[modTag.Index] == null) { return(CacheContext.TagCache.Index[modTag.Index]); // references an HO tag } else { // tag has already been converted if (TagMapping.ContainsKey(modTag.Index)) { return(CacheContext.TagCache.Index[TagMapping[modTag.Index]]); // get the matching tag in the destination package } else { CachedTagInstance newTag; if (modTag.Index <= MagicNumber) { newTag = CacheContext.GetTag(modTag.Index); } else if (!CacheContext.TryGetTag($"{modTag.Name}.{modTag.Group}", out newTag)) { newTag = CacheContext.TagCache.AllocateTag(modTag.Group); newTag.Name = modTag.Name; } TagMapping.Add(modTag.Index, newTag.Index); var definitionType = TagDefinition.Find(modTag.Group.Tag); var tagDefinition = CacheContext.Deserialize(new ModPackageTagSerializationContext(modPack.TagsStream, CacheContext, modPack, modTag), definitionType); tagDefinition = ConvertData(modPack, tagDefinition); if (definitionType == typeof(ForgeGlobalsDefinition)) { tagDefinition = ConvertForgeGlobals((ForgeGlobalsDefinition)tagDefinition); } else if (definitionType == typeof(Scenario)) { tagDefinition = ConvertScenario(modPack, (Scenario)tagDefinition); } CacheContext.Serialize(CacheStream, newTag, tagDefinition); foreach (var resourcePointer in modTag.ResourcePointerOffsets) { newTag.AddResourceOffset(resourcePointer); } return(newTag); } } }
public void ConvertScriptTagReferenceExpressionData(ModPackageExtended modPack, HsSyntaxNode expr) { var tagIndex = BitConverter.ToInt32(expr.Data.ToArray(), 0); CachedTagInstance tag = null; if (modPack.Tags.Index[tagIndex] == null) { return; // references an HO tag } if (TagMapping.ContainsKey(tagIndex)) { tag = CacheContext.TagCache.Index[TagMapping[tagIndex]]; } expr.Data = BitConverter.GetBytes(tag?.Index ?? -1).ToArray(); // apply proper tag index or set to -1 }
private T ConvertStructure <T>(ModPackageExtended sourceModPack, ModPackageExtended destModPack, T data) where T : TagStructure { foreach (var tagFieldInfo in TagStructure.GetTagFieldEnumerable(data.GetType(), CacheContext.Version)) { var oldValue = tagFieldInfo.GetValue(data); if (oldValue is null) { continue; } var newValue = ConvertData(sourceModPack, destModPack, oldValue); tagFieldInfo.SetValue(data, newValue); } return(data); }
private IList ConvertCollection(ModPackageExtended sourceModPack, ModPackageExtended destModPack, IList collection) { // return early where possible if (collection is null || collection.Count == 0) { return(collection); } for (var i = 0; i < collection.Count; i++) { var oldValue = collection[i]; var newValue = ConvertData(sourceModPack, destModPack, oldValue); collection[i] = newValue; } return(collection); }
private CachedTagInstance ConvertCachedTagInstance(ModPackageExtended sourceModPack, ModPackageExtended destModPack, CachedTagInstance tag) { // Determine if tag requires conversion // if tag is in the sourceModPack if (sourceModPack.Tags.Index[tag.Index] == null) { return(tag); } else { var name = sourceModPack.TagNames.ContainsKey(tag.Index) ? sourceModPack.TagNames[tag.Index] : $"0x{tag.Index:X4}"; // tag has already been converted if (TagMapping.ContainsKey(tag.Index)) { return(destModPack.Tags.Index[TagMapping[tag.Index]]); // get the matching tag in the destination package } else { // mimic the tag allocation process CachedTagInstance newTag; if (tag.Index < HOTagCount) { newTag = destModPack.Tags.Index[tag.Index]; } else { newTag = destModPack.Tags.Index[NextTagIndex]; NextTagIndex++; } var tagDefinition = CacheContext.Deserialize(sourceModPack.TagsStream, tag); tagDefinition = ConvertData(sourceModPack, destModPack, tagDefinition); CacheContext.Serialize(destModPack.TagsStream, newTag, tagDefinition); if (sourceModPack.TagNames.ContainsKey(tag.Index)) { destModPack.TagNames.Add(newTag.Index, sourceModPack.TagNames[tag.Index]); } TagMapping.Add(tag.Index, newTag.Index); return(newTag); } } }
private PageableResource ConvertPageableResource(ModPackageExtended modPack, PageableResource resource) { if (resource.Page.Index == -1) { return(resource); } var resourceStream = new MemoryStream(); modPack.Resources.Decompress(modPack.ResourcesStream, resource.Page.Index, resource.Page.CompressedBlockSize, resourceStream); resourceStream.Position = 0; resource.ChangeLocation(ResourceLocation.ResourcesB); resource.Page.OldFlags &= ~OldRawPageFlags.InMods; CacheContext.AddResource(resource, resourceStream); return(resource); }
public override object Execute(List <string> args) { if (args.Count != 2) { return(false); } var modPackage1 = new ModPackageExtended(new FileInfo(args[0])); var modPackage2 = new ModPackageExtended(new FileInfo(args[1])); var resultPackage = new ModPackageExtended(); CacheContext.CreateTagCache(resultPackage.TagsStream); resultPackage.Tags = new TagCache(resultPackage.TagsStream, new Dictionary <int, string>()); CacheContext.CreateResourceCache(resultPackage.ResourcesStream); resultPackage.Resources = new ResourceCache(resultPackage.ResourcesStream); // allocate all tags for mod package int maxTagCount = Math.Max(modPackage1.Tags.Index.Count, modPackage2.Tags.Index.Count); for (int i = 0; i < maxTagCount; i++) { resultPackage.Tags.AllocateTag(); } // // Merge tags that overwrite existing tags // // Assume current cache has no mods for (int i = 0; i < CacheContext.TagCache.Index.Count; i++) { var tag1 = modPackage1.Tags.Index[i]; var tag2 = modPackage1.Tags.Index[i]; var name1 = modPackage1.TagNames.ContainsKey(i) ? modPackage1.TagNames[i] : $"0x{i:X4}"; var name2 = modPackage2.TagNames.ContainsKey(i) ? modPackage2.TagNames[i] : $"0x{i:X4}"; if (tag1 != null) { ConvertCachedTagInstance(modPackage1, resultPackage, tag1); } else if (tag2 != null) { ConvertCachedTagInstance(modPackage2, resultPackage, tag2); } else { resultPackage.Tags.AllocateTag(); continue; } } // // Merge each mod packages new tags. If tag names compete, package 1 has priority // for (int i = CacheContext.TagCache.Index.Count; i < modPackage1.Tags.Index.Count; i++) { var tag1 = modPackage1.Tags.Index[i]; if (tag1 != null) { ConvertCachedTagInstance(modPackage1, resultPackage, tag1); } } for (int i = CacheContext.TagCache.Index.Count; i < modPackage2.Tags.Index.Count; i++) { var tag2 = modPackage2.Tags.Index[i]; if (tag2 != null) { ConvertCachedTagInstance(modPackage2, resultPackage, tag2); } } // // Create resulting mod package header and info // resultPackage.Header = modPackage1.Header; resultPackage.Metadata = modPackage1.Metadata; resultPackage.Save(new FileInfo($"merge_test_{args[0]}")); return(true); }
public ModPackageTagSerializationContext(Stream stream, HaloOnlineCacheContext context, ModPackageExtended package, CachedTagInstance tag) : base(stream, context, tag) { Package = package; }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } var filePath = args[0]; if (!File.Exists(filePath)) { Console.WriteLine($"File {filePath} does not exist!"); return(false); } CacheStream = CacheContext.OpenTagCacheReadWrite(); var modPackage = new ModPackageExtended(new FileInfo(filePath)); for (int i = 0; i < modPackage.Tags.Index.Count; i++) { var modTag = modPackage.Tags.Index[i]; if (modTag != null) { if (!TagMapping.ContainsKey(modTag.Index)) { ConvertCachedTagInstance(modPackage, modTag); } } } // fixup map files foreach (var mapFile in modPackage.MapFileStreams) { using (var reader = new EndianReader(mapFile)) { MapFile map = new MapFile(); map.Read(reader); var modIndex = map.Header.GetScenarioTagIndex(); TagMapping.TryGetValue(modIndex, out int newScnrIndex); map.Header.SetScenarioTagIndex(newScnrIndex); var mapName = map.Header.GetName(); var mapPath = $"{CacheContext.Directory.FullName}\\{mapName}.map"; var file = new FileInfo(mapPath); var fileStream = file.OpenWrite(); using (var writer = new EndianWriter(fileStream, map.EndianFormat)) { map.Write(writer); } } } // apply .campaign file var campaignFilepath = $"{CacheContext.Directory.FullName}\\halo3.campaign"; var campaignFile = new FileInfo(campaignFilepath); var campaignFileStream = campaignFile.OpenWrite(); modPackage.CampaignFileStream.CopyTo(campaignFileStream); campaignFileStream.Close(); CacheStream.Close(); CacheStream.Dispose(); CacheContext.SaveTagNames(); return(true); }
public void ConvertScriptExpression(ModPackageExtended modPack, HsSyntaxNode expr) { ConvertScriptExpressionData(modPack, expr); }
public override object Execute(List <string> args) { if (args.Count < 1 || args.Count > 7) { return(false); } string packageName; string line = null; // // Parse input options // while (args.Count != 1) { var arg = args[0].ToLower(); switch (arg) { case "tagfile": Options |= ExportOptions.TagFile; break; case "taglist": Options |= ExportOptions.TagList; break; case "tagbounds": Options |= ExportOptions.TagBounds; break; case "mapfiles": case "mapfile": Options |= ExportOptions.MapFiles; break; case "campaignfile": Options |= ExportOptions.CampaignFile; break; default: Console.WriteLine($"Invalid argument: {arg}"); break; } args.RemoveAt(0); } packageName = args[0]; ModPackage = new ModPackageExtended(); // // Process options and create mod package // CacheContext.CreateTagCache(ModPackage.TagsStream); ModPackage.Tags = new TagCache(ModPackage.TagsStream, new Dictionary <int, string>()); CacheContext.CreateResourceCache(ModPackage.ResourcesStream); ModPackage.Resources = new ResourceCache(ModPackage.ResourcesStream); CreateDescription(); var tagIndices = new HashSet <int>(); if (Options.HasFlag(ExportOptions.TagBounds)) { int?fromIndex = -1; int?toIndex = CacheContext.TagCache.Index.NonNull().Last().Index; Console.WriteLine("Please specify the start index to be used:"); string input = line = Console.ReadLine().TrimStart().TrimEnd(); if (CacheContext.TryGetTag(input, out var fromInstance) && fromInstance != null) { fromIndex = fromInstance.Index; } if (fromIndex != -1) { Console.WriteLine("Please specify the end index to be used (press enter to skip):"); input = Console.ReadLine().TrimStart().TrimEnd(); if (input != "") { if (CacheContext.TryGetTag(input, out var toInstance) && fromInstance != null) { toIndex = toInstance.Index; } else { Console.WriteLine($"Invalid end index"); return(false); } } } else { Console.WriteLine($"Invalid start index"); return(false); } // add tags to list foreach (var entry in Enumerable.Range(fromIndex.Value, toIndex.Value - fromIndex.Value + 1)) { if (!tagIndices.Contains(entry) && CacheContext.GetTag(entry) != null) { tagIndices.Add(entry); } } } if (Options.HasFlag(ExportOptions.TagFile)) { Console.WriteLine("Enter the name of the tag list file (csv): "); string tagFile = Console.ReadLine().Trim(); using (var tagListStream = File.Open(tagFile, FileMode.Open, FileAccess.Read)) { var reader = new StreamReader(tagListStream); while (!reader.EndOfStream) { var tagName = reader.ReadLine(); if (CacheContext.TryGetTag(tagName, out var instance) && instance != null) { if (!tagIndices.Contains(instance.Index)) { tagIndices.Add(instance.Index); } else { Console.WriteLine($"Falied to find tag {tagName}"); } } } reader.Close(); } } if (Options.HasFlag(ExportOptions.TagList)) { Console.WriteLine("Please specify the tags to be used (enter an empty line to finish):"); while ((line = Console.ReadLine().TrimStart().TrimEnd()) != "") { if (CacheContext.TryGetTag(line, out var instance) && instance != null && !tagIndices.Contains(instance.Index)) { tagIndices.Add(instance.Index); } } } if (Options.HasFlag(ExportOptions.MapFiles)) { var mapFileNames = new HashSet <string>(); Console.WriteLine("Please specify the .map files to be used (enter an empty line to finish):"); while ((line = Console.ReadLine().TrimStart().TrimEnd()) != "") { if (!File.Exists(line)) { Console.WriteLine($"File {line} does not exist. Please enter a valid map file"); continue; } else { var mapFile = new FileInfo(line); if (mapFile.Extension != ".map") { Console.WriteLine($"File {line} is not a map file."); continue; } if (!mapFileNames.Contains(mapFile.FullName)) { mapFileNames.Add(mapFile.FullName); } } } AddMaps(mapFileNames); } if (Options.HasFlag(ExportOptions.CampaignFile)) { Console.WriteLine("Please specify the .campaign file to be used:"); while (true) { string campaignFileName = Console.ReadLine().TrimStart().TrimEnd(); if (!File.Exists(campaignFileName)) { Console.WriteLine($"File {line} does not exist."); } else { var file = new FileInfo(campaignFileName); if (file.Extension != ".campaign") { Console.WriteLine($"File {line} is not a campaign file."); continue; } else { AddCampaignMap(file); break; } } } } // // Use the tag list collected to create new mod package // Console.WriteLine("Building..."); AddTags(tagIndices); ModPackage.Save(new FileInfo(packageName)); Console.WriteLine("Done!"); return(true); }