public DatumIndex InjectTag(ExtractedTag tag, IStream stream) { if (tag == null) { throw new ArgumentNullException("tag is null"); } // Don't inject the tag if it's already been injected DatumIndex newIndex; if (_tagIndices.TryGetValue(tag, out newIndex)) { return(newIndex); } // Make sure there isn't already a tag with the given name ITag existingTag = _cacheFile.Tags.FindTagByName(tag.Name, tag.Class, _cacheFile.FileNames); if (existingTag != null) { return(existingTag.Index); } // Look up the tag's datablock to get its size and allocate a tag for it DataBlock tagData = _container.FindDataBlock(tag.OriginalAddress); if (_resources == null && BlockNeedsResources(tagData)) { // If the tag relies on resources and that info isn't available, throw it out LoadResourceTable(stream); if (_resources == null) { return(DatumIndex.Null); } } ITag newTag = _cacheFile.Tags.AddTag(tag.Class, tagData.Data.Length, stream); _tagIndices[tag] = newTag.Index; _cacheFile.FileNames.SetTagName(newTag, tag.Name); // Write the data WriteDataBlock(tagData, newTag.MetaLocation, stream); // Make the tag load LoadZoneSets(stream); if (_zoneSets != null && _zoneSets.GlobalZoneSet != null) { _zoneSets.GlobalZoneSet.ActivateTag(newTag, true); } return(newTag.Index); }
public DatumIndex InjectTag(ExtractedTag tag, IStream stream) { if (tag == null) throw new ArgumentNullException("tag is null"); // Don't inject the tag if it's already been injected DatumIndex newIndex; if (_tagIndices.TryGetValue(tag, out newIndex)) return newIndex; // Make sure there isn't already a tag with the given name ITag existingTag = _cacheFile.Tags.FindTagByName(tag.Name, tag.Class, _cacheFile.FileNames); if (existingTag != null) return existingTag.Index; // If the tag has made it this far but is a sound, make everyone (especially gerit) shut up. if (tag.Class == SoundClass) return DatumIndex.Null; // Look up the tag's datablock to get its size and allocate a tag for it DataBlock tagData = _container.FindDataBlock(tag.OriginalAddress); if (_resources == null && BlockNeedsResources(tagData)) { // If the tag relies on resources and that info isn't available, throw it out LoadResourceTable(stream); if (_resources == null) return DatumIndex.Null; } ITag newTag = _cacheFile.Tags.AddTag(tag.Class, tagData.Data.Length, stream); _tagIndices[tag] = newTag.Index; _cacheFile.FileNames.SetTagName(newTag, tag.Name); // Write the data WriteDataBlock(tagData, newTag.MetaLocation, stream, newTag); // Make the tag load LoadZoneSets(stream); if (_zoneSets != null && _zoneSets.GlobalZoneSet != null) _zoneSets.GlobalZoneSet.ActivateTag(newTag, true); // If its class matches one of the valid simulation class names, add it to the simulation definition table if (_cacheFile.SimulationDefinitions != null && _simulationClasses.Contains(CharConstant.ToString(newTag.Class.Magic))) _cacheFile.SimulationDefinitions.Add(newTag); return newTag.Index; }
public DatumIndex InjectTag(ExtractedTag tag, IStream stream) { string tagnameuniqifier = ""; if (tag == null) { throw new ArgumentNullException("tag is null"); } // Don't inject the tag if it's already been injected DatumIndex newIndex; if (_tagIndices.TryGetValue(tag, out newIndex)) { return(newIndex); } // Make sure there isn't already a tag with the given name ITag existingTag = _cacheFile.Tags.FindTagByName(tag.Name, tag.Group, _cacheFile.FileNames); if (existingTag != null) { //check if we are doing shader tweaks if (_renameShaders && _shaderGroups.Contains(CharConstant.ToString(tag.Group))) { //append old tagid to make it unique tagnameuniqifier = "_" + tag.OriginalIndex.ToString(); //make sure the tag didnt come from this exact map if (existingTag.Index == tag.OriginalIndex) { return(existingTag.Index); } //make sure the appended name isn't already present existingTag = _cacheFile.Tags.FindTagByName(tag.Name + tagnameuniqifier, tag.Group, _cacheFile.FileNames); if (existingTag != null) { return(existingTag.Index); } } else { return(existingTag.Index); } } if (!_keepSound && tag.Group == SoundGroup) { return(DatumIndex.Null); } //PCA resource type is not always present, so get rid of 'em for now if (tag.Group == PCAGroup) { return(DatumIndex.Null); } // Look up the tag's datablock to get its size and allocate a tag for it DataBlock tagData = _container.FindDataBlock(tag.OriginalAddress); if (_resources == null && BlockNeedsResources(tagData)) { // If the tag relies on resources and that info isn't available, throw it out LoadResourceTable(stream); if (_resources == null) { return(DatumIndex.Null); } } if (_soundResources == null && BlockNeedsSounds(tagData)) { // If the tag relies on sound resources and that info isn't available, throw it out LoadSoundResourceTable(stream); if (_soundResources == null) { return(DatumIndex.Null); } } ITag newTag = _cacheFile.Tags.AddTag(tag.Group, tagData.Data.Length, stream); _tagIndices[tag] = newTag.Index; _cacheFile.FileNames.SetTagName(newTag, tag.Name + tagnameuniqifier); // Write the data WriteDataBlock(tagData, newTag.MetaLocation, stream, newTag); // Make the tag load LoadZoneSets(stream); if (_zoneSets != null) { _zoneSets.ExpandAllTags(newTag.Index.Index); if (_zoneSets.GlobalZoneSet != null) { _zoneSets.GlobalZoneSet.ActivateTag(newTag, true); } } // If its group matches one of the valid simulation group names, add it to the simulation definition table if (_cacheFile.SimulationDefinitions != null && _simulationGroups.Contains(CharConstant.ToString(newTag.Group.Magic))) { _cacheFile.SimulationDefinitions.Add(newTag); } return(newTag.Index); }
/// <summary> /// Adds information about an extracted tag to the container. /// </summary> /// <param name="tag">The tag information to add.</param> public void AddTag(ExtractedTag tag) { _tagsByIndex[tag.OriginalIndex] = tag; }
private void contextExtract_Click(object sender, RoutedEventArgs e) { // Get the menu item and the tag var item = e.Source as MenuItem; if (item == null) return; var tag = item.DataContext as TagEntry; if (tag == null) return; // Ask where to save the extracted tag collection var sfd = new SaveFileDialog { Title = "Save Tag Set", Filter = "Tag Container Files|*.tagc" }; bool? result = sfd.ShowDialog(); if (!result.Value) return; // Make a tag container var container = new TagContainer(); // Recursively extract tags var tagsToProcess = new Queue<ITag>(); var tagsProcessed = new HashSet<ITag>(); var resourcesToProcess = new Queue<DatumIndex>(); var resourcesProcessed = new HashSet<DatumIndex>(); var resourcePagesProcessed = new HashSet<ResourcePage>(); tagsToProcess.Enqueue(tag.RawTag); ResourceTable resources = null; using (IReader reader = _mapManager.OpenRead()) { while (tagsToProcess.Count > 0) { ITag currentTag = tagsToProcess.Dequeue(); if (tagsProcessed.Contains(currentTag)) continue; // Get the plugin path string className = VariousFunctions.SterilizeTagClassName(CharConstant.ToString(currentTag.Class.Magic)).Trim(); string pluginPath = string.Format("{0}\\{1}\\{2}.xml", VariousFunctions.GetApplicationLocation() + @"Plugins", _buildInfo.Settings.GetSetting<string>("plugins"), className); // Extract dem data blocks var blockBuilder = new DataBlockBuilder(reader, currentTag.MetaLocation, _cacheFile, _buildInfo); using (XmlReader pluginReader = XmlReader.Create(pluginPath)) AssemblyPluginLoader.LoadPlugin(pluginReader, blockBuilder); foreach (DataBlock block in blockBuilder.DataBlocks) container.AddDataBlock(block); // Add data for the tag that was extracted string tagName = _cacheFile.FileNames.GetTagName(currentTag) ?? currentTag.Index.ToString(); var extractedTag = new ExtractedTag(currentTag.Index, currentTag.MetaLocation.AsPointer(), currentTag.Class.Magic, tagName); container.AddTag(extractedTag); // Mark the tag as processed and then enqueue all of its child tags and resources tagsProcessed.Add(currentTag); foreach (DatumIndex tagRef in blockBuilder.ReferencedTags) tagsToProcess.Enqueue(_cacheFile.Tags[tagRef]); foreach (DatumIndex resource in blockBuilder.ReferencedResources) resourcesToProcess.Enqueue(resource); } // Load the resource table in if necessary if (resourcesToProcess.Count > 0) resources = _cacheFile.Resources.LoadResourceTable(reader); } // Extract resource info if (resources != null) { while (resourcesToProcess.Count > 0) { DatumIndex index = resourcesToProcess.Dequeue(); if (resourcesProcessed.Contains(index)) continue; // Add the resource Resource resource = resources.Resources[index.Index]; container.AddResource(new ExtractedResourceInfo(resource)); // Add data for its pages if (resource.Location == null) continue; if (resource.Location.PrimaryPage != null && !resourcePagesProcessed.Contains(resource.Location.PrimaryPage)) { container.AddResourcePage(resource.Location.PrimaryPage); resourcePagesProcessed.Add(resource.Location.PrimaryPage); } if (resource.Location.SecondaryPage == null || resourcePagesProcessed.Contains(resource.Location.SecondaryPage)) continue; container.AddResourcePage(resource.Location.SecondaryPage); resourcePagesProcessed.Add(resource.Location.SecondaryPage); } } // Write it to a file using (var writer = new EndianWriter(File.Open(sfd.FileName, FileMode.Create, FileAccess.Write), Endian.BigEndian)) TagContainerWriter.WriteTagContainer(container, writer); // YAY! MetroMessageBox.Show("Extraction Successful", "Extracted " + container.Tags.Count + " tag(s), " + container.DataBlocks.Count + " data block(s), " + container.ResourcePages.Count + " resource page pointer(s), and " + container.Resources.Count + " resource pointer(s)."); }
private void extractTags(bool withRaw, TagEntry tag) { // Ask where to save the extracted tag collection var sfd = new SaveFileDialog { Title = "Save Tag Set", Filter = "Tag Container Files|*.tagc" }; bool? result = sfd.ShowDialog(); if (!result.Value) return; // Make a tag container var container = new TagContainer(); // Recursively extract tags var tagsToProcess = new Queue<ITag>(); var tagsProcessed = new HashSet<ITag>(); var resourcesToProcess = new Queue<DatumIndex>(); var resourcesProcessed = new HashSet<DatumIndex>(); var resourcePagesProcessed = new HashSet<ResourcePage>(); tagsToProcess.Enqueue(tag.RawTag); ResourceTable resources = null; using (var reader = _mapManager.OpenRead()) { while (tagsToProcess.Count > 0) { var currentTag = tagsToProcess.Dequeue(); if (tagsProcessed.Contains(currentTag)) continue; // Get the plugin path var className = VariousFunctions.SterilizeTagClassName(CharConstant.ToString(currentTag.Class.Magic)).Trim(); var pluginPath = string.Format("{0}\\{1}\\{2}.xml", VariousFunctions.GetApplicationLocation() + @"Plugins", _buildInfo.Settings.GetSetting<string>("plugins"), className); // Extract dem data blocks var blockBuilder = new DataBlockBuilder(reader, currentTag, _cacheFile, _buildInfo); using (var pluginReader = XmlReader.Create(pluginPath)) AssemblyPluginLoader.LoadPlugin(pluginReader, blockBuilder); foreach (var block in blockBuilder.DataBlocks) container.AddDataBlock(block); // Add data for the tag that was extracted var tagName = _cacheFile.FileNames.GetTagName(currentTag) ?? currentTag.Index.ToString(); var extractedTag = new ExtractedTag(currentTag.Index, currentTag.MetaLocation.AsPointer(), currentTag.Class.Magic, tagName); container.AddTag(extractedTag); // Mark the tag as processed and then enqueue all of its child tags and resources tagsProcessed.Add(currentTag); foreach (var tagRef in blockBuilder.ReferencedTags) tagsToProcess.Enqueue(_cacheFile.Tags[tagRef]); foreach (var resource in blockBuilder.ReferencedResources) resourcesToProcess.Enqueue(resource); } // Load the resource table in if necessary if (resourcesToProcess.Count > 0) resources = _cacheFile.Resources.LoadResourceTable(reader); } // Extract resource info if (resources != null) { while (resourcesToProcess.Count > 0) { var index = resourcesToProcess.Dequeue(); if (resourcesProcessed.Contains(index)) continue; // Add the resource var resource = resources.Resources[index.Index]; container.AddResource(new ExtractedResourceInfo(index, resource)); // Add data for its pages if (resource.Location == null) continue; if (resource.Location.PrimaryPage != null && !resourcePagesProcessed.Contains(resource.Location.PrimaryPage)) { container.AddResourcePage(resource.Location.PrimaryPage); resourcePagesProcessed.Add(resource.Location.PrimaryPage); if (withRaw) { using (var fileStream = File.OpenRead(_cacheLocation)) { var resourceFile = _cacheFile; Stream resourceStream = fileStream; if (resource.Location.PrimaryPage.FilePath != null) { var resourceCacheInfo = App.AssemblyStorage.AssemblySettings.HalomapResourceCachePaths.FirstOrDefault( r => r.EngineName == _buildInfo.Name); var resourceCachePath = (resourceCacheInfo != null) ? resourceCacheInfo.ResourceCachePath : Path.GetDirectoryName(_cacheLocation); resourceCachePath = Path.Combine(resourceCachePath ?? "", Path.GetFileName(resource.Location.PrimaryPage.FilePath)); if (!File.Exists(resourceCachePath)) { MetroMessageBox.Show("Unable to extract tag", "Unable to extract tag, because a resource it relies on is in a external cache '{0}' that could not be found. Check Assembly's settings and set the file path to resource caches."); return; } resourceStream = File.OpenRead(resourceCachePath); resourceFile = new ThirdGenCacheFile(new EndianReader(resourceStream, Endian.BigEndian), _buildInfo, _cacheFile.BuildString); } var extractor = new ResourcePageExtractor(resourceFile); byte[] pageData; using (var pageStream = new MemoryStream()) { extractor.ExtractPage(resource.Location.PrimaryPage, resourceStream, pageStream); pageData = new byte[pageStream.Length]; Buffer.BlockCopy(pageStream.GetBuffer(), 0, pageData, 0, (int) pageStream.Length); } container.AddExtractedResourcePage(new ExtractedPage(pageData, resource.Location.PrimaryPage.Index)); } } } if (resource.Location.SecondaryPage == null || resourcePagesProcessed.Contains(resource.Location.SecondaryPage)) continue; container.AddResourcePage(resource.Location.SecondaryPage); resourcePagesProcessed.Add(resource.Location.SecondaryPage); if (withRaw) { using (var fileStream = File.OpenRead(_cacheLocation)) { var resourceFile = _cacheFile; Stream resourceStream = fileStream; if (resource.Location.SecondaryPage.FilePath != null) { var resourceCacheInfo = App.AssemblyStorage.AssemblySettings.HalomapResourceCachePaths.FirstOrDefault( r => r.EngineName == _buildInfo.Name); var resourceCachePath = (resourceCacheInfo != null) ? resourceCacheInfo.ResourceCachePath : Path.GetDirectoryName(_cacheLocation); resourceCachePath = Path.Combine(resourceCachePath ?? "", Path.GetFileName(resource.Location.SecondaryPage.FilePath)); if (!File.Exists(resourceCachePath)) { MetroMessageBox.Show("Unable to extract tag", "Unable to extract tag, because a resource it relies on is in a external cache '{0}' that could not be found. Check Assembly's settings and set the file path to resource caches."); return; } resourceStream = File.OpenRead(resourceCachePath); resourceFile = new ThirdGenCacheFile(new EndianReader(resourceStream, Endian.BigEndian), _buildInfo, _cacheFile.BuildString); } var extractor = new ResourcePageExtractor(resourceFile); byte[] pageData; using (var pageStream = new MemoryStream()) { extractor.ExtractPage(resource.Location.SecondaryPage, resourceStream, pageStream); pageData = new byte[pageStream.Length]; Buffer.BlockCopy(pageStream.GetBuffer(), 0, pageData, 0, (int)pageStream.Length); } container.AddExtractedResourcePage(new ExtractedPage(pageData, resource.Location.SecondaryPage.Index)); } } } } // Write it to a file using (var writer = new EndianWriter(File.Open(sfd.FileName, FileMode.Create, FileAccess.Write), Endian.BigEndian)) TagContainerWriter.WriteTagContainer(container, writer); // YAY! MetroMessageBox.Show("Extraction Successful", "Extracted " + container.Tags.Count + " tag(s), " + container.DataBlocks.Count + " data block(s), " + container.ResourcePages.Count + " resource page pointer(s), " + container.ExtractedResourcePages.Count + " extracted resource page(s), and " + container.Resources.Count + " resource pointer(s)."); }
private void contextDuplicate_Click(object sender, RoutedEventArgs e) { // Get the menu item and the tag var item = e.Source as MenuItem; if (item == null) return; var tag = item.DataContext as TagEntry; if (tag == null) return; // TODO: Make this into a dialog with more options string newName; while (true) { newName = MetroInputBox.Show("Duplicate Tag", "Please enter a name for the new tag.", tag.TagFileName, "Enter a name."); if (newName == null) return; if (newName != tag.TagFileName && _cacheFile.Tags.FindTagByName(newName, tag.RawTag.Class, _cacheFile.FileNames) == null) break; MetroMessageBox.Show("Duplicate Tag", "Please enter a name that is different from the original and that is not in use."); } // Make a tag container for the tag and then inject it // TODO: A lot of this was copied and pasted from the tag extraction code...need to clean things up var container = new TagContainer(); using (var stream = _mapManager.OpenReadWrite()) { // Get the plugin path string className = VariousFunctions.SterilizeTagClassName(CharConstant.ToString(tag.RawTag.Class.Magic)).Trim(); string pluginPath = string.Format("{0}\\{1}\\{2}.xml", VariousFunctions.GetApplicationLocation() + @"Plugins", _buildInfo.Settings.GetSetting<string>("plugins"), className); // Extract data blocks var builder = new DataBlockBuilder(stream, tag.RawTag, _cacheFile, _buildInfo); using (XmlReader pluginReader = XmlReader.Create(pluginPath)) AssemblyPluginLoader.LoadPlugin(pluginReader, builder); foreach (var block in builder.DataBlocks) { // Remove non-datablock fixups because those are still valid // TODO: A better approach might be to just make DataBlockBuilder ignore these in the first place block.StringIDFixups.Clear(); block.ShaderFixups.Clear(); block.ResourceFixups.Clear(); block.TagFixups.Clear(); container.AddDataBlock(block); } var extracted = new ExtractedTag(tag.RawTag.Index, tag.RawTag.MetaLocation.AsPointer(), tag.RawTag.Class.Magic, newName); container.AddTag(extracted); // Now inject the container var injector = new TagContainerInjector(_cacheFile, container); injector.InjectTag(extracted, stream); injector.SaveChanges(stream); } LoadTags(); MetroMessageBox.Show("Duplicate Tag", "Tag duplicated successfully!"); }
public DatumIndex InjectTag(ExtractedTag tag, IStream stream) { if (tag == null) throw new ArgumentNullException("tag is null"); // Don't inject the tag if it's already been injected DatumIndex newIndex; if (_tagIndices.TryGetValue(tag, out newIndex)) return newIndex; // Make sure there isn't already a tag with the given name ITag existingTag = _cacheFile.Tags.FindTagByName(tag.Name, tag.Class, _cacheFile.FileNames); if (existingTag != null) return existingTag.Index; // Look up the tag's datablock to get its size and allocate a tag for it DataBlock tagData = _container.FindDataBlock(tag.OriginalAddress); ITag newTag = _cacheFile.Tags.AddTag(tag.Class, tagData.Data.Length, stream); _tagIndices[tag] = newTag.Index; _cacheFile.FileNames.SetTagName(newTag, tag.Name); // Write the data WriteDataBlock(tagData, newTag.MetaLocation, stream); // Make the tag load LoadZoneSets(stream); _zoneSets.GlobalZoneSet.ActivateTag(newTag, true); return newTag.Index; }
public DatumIndex InjectTag(ExtractedTag tag, IStream stream) { if (tag == null) { throw new ArgumentNullException("tag is null"); } // Don't inject the tag if it's already been injected DatumIndex newIndex; if (_tagIndices.TryGetValue(tag, out newIndex)) { return(newIndex); } // Make sure there isn't already a tag with the given name ITag existingTag = _cacheFile.Tags.FindTagByName(tag.Name, tag.Class, _cacheFile.FileNames); if (existingTag != null) { return(existingTag.Index); } // If the tag has made it this far but is a sound, make everyone (especially gerit) shut up. if (tag.Class == SoundClass) { return(DatumIndex.Null); } // Look up the tag's datablock to get its size and allocate a tag for it DataBlock tagData = _container.FindDataBlock(tag.OriginalAddress); if (_resources == null && BlockNeedsResources(tagData)) { // If the tag relies on resources and that info isn't available, throw it out LoadResourceTable(stream); if (_resources == null) { return(DatumIndex.Null); } } ITag newTag = _cacheFile.Tags.AddTag(tag.Class, tagData.Data.Length, stream); _tagIndices[tag] = newTag.Index; _cacheFile.FileNames.SetTagName(newTag, tag.Name); // Write the data WriteDataBlock(tagData, newTag.MetaLocation, stream, newTag); // Make the tag load LoadZoneSets(stream); if (_zoneSets != null && _zoneSets.GlobalZoneSet != null) { _zoneSets.GlobalZoneSet.ActivateTag(newTag, true); } // If its class matches one of the valid simulation class names, add it to the simulation definition table if (_cacheFile.SimulationDefinitions != null && _simulationClasses.Contains(CharConstant.ToString(newTag.Class.Magic))) { _cacheFile.SimulationDefinitions.Add(newTag); } return(newTag.Index); }