Пример #1
0
        public async Task <FullImcInfo> GetFullImcInfo(IItemModel item, IndexFile index = null, ModList modlist = null)
        {
            FullImcInfo info = null;

            try
            {
                var imcPath = GetImcPath(item);
                var path    = imcPath.Folder + "/" + imcPath.File;
                info = await GetFullImcInfo(path, index, modlist);
            } catch
            {
                // Some dual wield items don't have a second IMC, and just default to the first.
                if (typeof(XivGear) == item.GetType())
                {
                    var gear = (XivGear)item;
                    if (gear != null && gear.PairedItem != null)
                    {
                        var pair    = gear.PairedItem;
                        var imcPath = GetImcPath(pair);
                        var path    = imcPath.Folder + "/" + imcPath.File;
                        return(await(GetFullImcInfo(path, index, modlist)));
                    }
                }
                else
                {
                    throw new InvalidDataException("Unable to get IMC data for item: " + item.Name);
                }
            }

            return(info);
        }
Пример #2
0
        public async Task SaveFullImcInfo(FullImcInfo info, string path, string itemName = null, string category = null, string source = null)
        {
            var index = new Index(_gameDirectory);
            var dat   = new Dat(_gameDirectory);


            var imcOffset = await index.GetDataOffset(path);

            // No writing new IMC files.
            if (imcOffset == 0)
            {
                throw new InvalidDataException($"Could not find offset for {path}");
            }

            var data = new List <byte>();

            // 4 Header bytes.
            data.AddRange(BitConverter.GetBytes((short)info.SubsetCount));
            data.AddRange(BitConverter.GetBytes((short)info.TypeIdentifier));

            // The rest of this is easy, it's literally just post all the sets in order.
            foreach (var entry in info.DefaultSubset)
            {
                data.AddRange(entry.GetBytes());
            }

            foreach (var set in info.SubsetList)
            {
                foreach (var entry in set)
                {
                    data.AddRange(entry.GetBytes());
                }
            }

            // That's it.

            // Get outta here with your fancy operators
            //itemName ??= Path.GetFileName(path);
            //category ??= "Meta";
            //source ??= "Internal";

            itemName = itemName ?? Path.GetFileName(path);
            category = category ?? "Meta";
            source   = source ?? "Internal";

            await dat.ImportType2Data(data.ToArray(), itemName, path, category, source);
        }
Пример #3
0
 public async Task SaveFullImcInfo(FullImcInfo info, IItemModel item)
 {
     try
     {
         var imcPath = GetImcPath(item);
         var path    = imcPath.Folder + "/" + imcPath.File;
         await SaveFullImcInfo(info, path);
     }
     catch
     {
         // Some dual wield items don't have a second IMC, and just default to the first.
         var gear = (XivGear)item;
         if (gear != null && gear.PairedItem != null)
         {
             var pair    = gear.PairedItem;
             var imcPath = GetImcPath(pair);
             var path    = imcPath.Folder + "/" + imcPath.File;
             await(SaveFullImcInfo(info, path));
         }
     }
     return;
 }
Пример #4
0
        public async Task <FullImcInfo> GetFullImcInfo(IItemModel item)
        {
            FullImcInfo info = null;

            try
            {
                var imcPath = GetImcPath(item);
                var path    = imcPath.Folder + "/" + imcPath.File;
                info = await GetFullImcInfo(path);
            } catch
            {
                // Some dual wield items don't have a second IMC, and just default to the first.
                var gear = (XivGear)item;
                if (gear != null && gear.PairedItem != null)
                {
                    var pair    = gear.PairedItem;
                    var imcPath = GetImcPath(pair);
                    var path    = imcPath.Folder + "/" + imcPath.File;
                    return(await(GetFullImcInfo(path)));
                }
            }

            return(info);
        }
Пример #5
0
        public async Task SaveFullImcInfo(FullImcInfo info, string path, string source, IItem referenceItem = null, IndexFile cachedIndexFile = null, ModList cachedModList = null)
        {
            if (info == null || info.TypeIdentifier != ImcType.Set && info.TypeIdentifier != ImcType.NonSet)
            {
                throw new InvalidDataException("Cannot save invalid IMC file.");
            }

            var index = new Index(_gameDirectory);
            var dat   = new Dat(_gameDirectory);

            var data = new List <byte>();


            // 4 Header bytes.
            data.AddRange(BitConverter.GetBytes((short)info.SubsetCount));
            data.AddRange(BitConverter.GetBytes((short)info.TypeIdentifier));

            // The rest of this is easy, it's literally just post all the sets in order.
            foreach (var entry in info.DefaultSubset)
            {
                data.AddRange(entry.GetBytes(info.TypeIdentifier));
            }

            foreach (var set in info.SubsetList)
            {
                foreach (var entry in set)
                {
                    data.AddRange(entry.GetBytes(info.TypeIdentifier));
                }
            }

            // That's it.
            source ??= "Unknown";

            await dat.ImportType2Data(data.ToArray(), path, source, referenceItem, cachedIndexFile, cachedModList);
        }
Пример #6
0
        /// <summary>
        /// Gets the full IMC information for a given item
        /// </summary>
        /// <param name="item"></param>
        /// <param name="useSecondary">Determines if the SecondaryModelInfo should be used instead.(XivGear only)</param>
        /// <returns>The ImcData data</returns>
        public async Task <FullImcInfo> GetFullImcInfo(string path)
        {
            var index = new Index(_gameDirectory);
            var dat   = new Dat(_gameDirectory);


            var imcOffset = await index.GetDataOffset(path);

            if (imcOffset == 0)
            {
                throw new InvalidDataException($"Could not find offset for {path}");
            }

            var imcByteData = await dat.GetType2Data(imcOffset, IOUtil.GetDataFileFromPath(path));

            return(await Task.Run(() =>
            {
                using (var br = new BinaryReader(new MemoryStream(imcByteData)))
                {
                    var subsetCount = br.ReadInt16();
                    var identifier = br.ReadInt16();
                    var imcData = new FullImcInfo()
                    {
                        TypeIdentifier = (ImcType)identifier,
                        DefaultSubset = new List <XivImc>(),
                        SubsetList = new List <List <XivImc> >(subsetCount)
                    };

                    //weapons and monsters do not have variant sets
                    if (imcData.TypeIdentifier == ImcType.NonSet)
                    {
                        // This type uses the first short for both Variant and VFX.
                        byte variant = br.ReadByte();
                        byte unknown = br.ReadByte();
                        ushort mask = br.ReadUInt16();
                        ushort vfx = br.ReadUInt16();

                        imcData.DefaultSubset.Add(new XivImc
                        {
                            Variant = variant,
                            Unknown = unknown,
                            Mask = mask,
                            Vfx = variant
                        });

                        for (var i = 0; i < subsetCount; i++)
                        {
                            variant = br.ReadByte();
                            unknown = br.ReadByte();
                            mask = br.ReadUInt16();
                            vfx = br.ReadUInt16();

                            var newEntry = new XivImc
                            {
                                Variant = variant,
                                Unknown = unknown,
                                Mask = mask,
                                Vfx = vfx
                            };
                            var subset = new List <XivImc>()
                            {
                                newEntry
                            };
                            imcData.SubsetList.Add(subset);
                        }
                    }
                    else if (imcData.TypeIdentifier == ImcType.Set)
                    {
                        // Identifier used by Equipment.
                        imcData.DefaultSubset = new List <XivImc>()
                        {
                            new XivImc
                            {
                                Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                            },
                            new XivImc
                            {
                                Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                            },
                            new XivImc
                            {
                                Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                            },
                            new XivImc
                            {
                                Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                            },
                            new XivImc
                            {
                                Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                            },
                        };

                        for (var i = 0; i < subsetCount; i++)
                        {
                            // gets the data for each slot in the current variant set
                            var imcGear = new List <XivImc>()
                            {
                                new XivImc
                                {
                                    Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                                },
                                new XivImc
                                {
                                    Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                                },
                                new XivImc
                                {
                                    Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                                },
                                new XivImc
                                {
                                    Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                                },
                                new XivImc
                                {
                                    Variant = br.ReadByte(), Unknown = br.ReadByte(), Mask = br.ReadUInt16(), Vfx = br.ReadUInt16()
                                },
                            };
                            imcData.SubsetList.Add(imcGear);
                        }
                    }
                    else
                    {
                        throw new NotSupportedException("Unknown IMC Type Identifier. (Please report this item in the TexTools Discord #bug_reports channel.)");
                    }

                    return imcData;
                }
            }));
        }
        /// <summary>
        /// Updates the View/ViewModel with a new selected base item.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public async Task <bool> SetItem(IItem item, MainWindow mainWindow = null)
        {
            var gameDirectory = new DirectoryInfo(Properties.Settings.Default.FFXIV_Directory);

            _imc  = new Imc(gameDirectory, item.DataFile);
            _gear = new Gear(gameDirectory, XivLanguages.GetXivLanguage(Properties.Settings.Default.Application_Language));

            if (mainWindow != null)
            {
                _mainWindow = mainWindow;
            }
            _item = item;
            _tree.Items.Clear();
            IItemModel im = null;

            try
            {
                im = (IItemModel)item;
            } catch (Exception ex)
            {
                return(false);
            }

            if (im == null || im.ModelInfo == null)
            {
                return(false);
            }

            var topLevelItem = new TreeViewItem();

            topLevelItem.Header = "";
            if (im.ModelInfo.PrimaryID > 0)
            {
                topLevelItem.Header += CapFirst(item.GetPrimaryItemType().ToString()) + " #" + im.ModelInfo.PrimaryID.ToString().PadLeft(4, '0');
            }
            else
            {
                topLevelItem.Header += CapFirst(item.GetPrimaryItemType().ToString());
            }
            _tree.Items.Add(topLevelItem);


            var nextParent = topLevelItem;

            if (im.ModelInfo.SecondaryID > 0)
            {
                var nextNode = new TreeViewItem();
                nextNode.Header += CapFirst(item.GetSecondaryItemType().ToString()) + " #" + im.ModelInfo.SecondaryID.ToString().PadLeft(4, '0');
                nextParent.Items.Add(nextNode);
                nextParent.IsExpanded = true;
                nextParent            = nextNode;
            }

            var abbreviation = _item.GetItemSlotAbbreviation();

            if (abbreviation != "")
            {
                var nextNode = new TreeViewItem();
                nextNode.Header = Mdl.SlotAbbreviationDictionary.First(x => x.Value == abbreviation).Key;
                nextParent.Items.Add(nextNode);
                nextParent.IsExpanded = true;
                nextParent            = nextNode;
            }

            FullImcInfo fullInfo = null;

            try
            {
                fullInfo = await _imc.GetFullImcInfo(im);
            } catch (Exception ex)
            {
                // This item has no IMC file.
                var nextNode = new TreeViewItem();
                nextNode.Header      = im.Name;
                nextNode.DataContext = im;
                //nextNode.MouseDoubleClick += ItemNode_Activated;
                nextParent.Items.Add(nextNode);
                nextParent.IsExpanded = true;
                nextNode.IsSelected   = true;
                nextParent            = nextNode;

                // No shared items for things without IMC files, so just hide the view entirely?
                return(false);
            }
            var sharedList = await _gear.GetSameModelList(im);

            var myVariantNumber = fullInfo.GetEntry(im.ModelInfo.ImcSubsetID, im.GetItemSlotAbbreviation()).Variant;
            var myImcNumber     = im.ModelInfo.ImcSubsetID;

            var materialVariantHeaders = new Dictionary <int, TreeViewItem>();
            var imcVariantHeaders      = new Dictionary <int, TreeViewItem>();

            // TODO -
            // Add the Variant header nodes at the start, and only scan the IMC files when a

            TreeViewItem myMaterialHeader = null;
            TreeViewItem myImcHeader      = null;
            TreeViewItem myNode           = null;

            foreach (var i in sharedList)
            {
                // Get the Variant # information
                var info = fullInfo.GetEntry(i.ModelInfo.ImcSubsetID, i.GetItemSlotAbbreviation());
                if (info == null)
                {
                    // Invalid IMC Set ID for the item.
                    continue;
                }

                if (!materialVariantHeaders.ContainsKey(info.Variant))
                {
                    materialVariantHeaders.Add(info.Variant, new TreeViewItem());
                    materialVariantHeaders[info.Variant].Header      = "Material Variant #" + info.Variant;
                    materialVariantHeaders[info.Variant].DataContext = info.Variant;
                }

                if (!imcVariantHeaders.ContainsKey(i.ModelInfo.ImcSubsetID))
                {
                    imcVariantHeaders.Add(i.ModelInfo.ImcSubsetID, new TreeViewItem());
                    imcVariantHeaders[i.ModelInfo.ImcSubsetID].Header      = "IMC Variant #" + i.ModelInfo.ImcSubsetID;
                    imcVariantHeaders[i.ModelInfo.ImcSubsetID].DataContext = i.ModelInfo.ImcSubsetID;

                    var hiddenParts = MaskToHidenParts(info.Mask);
                    imcVariantHeaders[i.ModelInfo.ImcSubsetID].Header += " - Hidden Parts: ";

                    if (hiddenParts.Count > 0)
                    {
                        imcVariantHeaders[i.ModelInfo.ImcSubsetID].Header += String.Join(",", hiddenParts);
                    }
                    else
                    {
                        imcVariantHeaders[i.ModelInfo.ImcSubsetID].Header += "None";
                    }

                    materialVariantHeaders[info.Variant].Items.Add(imcVariantHeaders[i.ModelInfo.ImcSubsetID]);

                    if (i.ModelInfo.ImcSubsetID == myImcNumber)
                    {
                        myImcHeader = imcVariantHeaders[i.ModelInfo.ImcSubsetID];
                    }
                }

                var nextNode = new TreeViewItem();
                nextNode.Header = i.Name;


                nextNode.DataContext = i;
                imcVariantHeaders[i.ModelInfo.ImcSubsetID].Items.Add(nextNode);


                if (myMaterialHeader == null && info.Variant == myVariantNumber)
                {
                    myMaterialHeader = materialVariantHeaders[info.Variant];
                }

                if (i.Name == im.Name)
                {
                    myNode = nextNode;
                }
                else
                {
                    nextNode.MouseDoubleClick += ItemNode_Activated;
                }
            }

            var ordered = materialVariantHeaders.OrderBy(x => x.Key);

            foreach (var kv in ordered)
            {
                nextParent.Items.Add(kv.Value);
            }
            nextParent.IsExpanded = true;

            if (myMaterialHeader != null)
            {
                myMaterialHeader.IsExpanded = true;
            }
            if (myImcHeader != null)
            {
                myImcHeader.IsExpanded = true;
            }
            if (myNode != null)
            {
                myNode.IsSelected = true;
            }

            return(true);
        }
Пример #8
0
        /// <summary>
        /// Saves a set of IMC entries to file.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="entries"></param>
        /// <returns></returns>
        internal async Task SaveEntries(string path, string slot, List <XivImc> entries, IItem referenceItem = null, IndexFile cachedIndexFile = null, ModList cachedModList = null)
        {
            var dat   = new Dat(_gameDirectory);
            var index = new Index(_gameDirectory);

            var exists = await index.FileExists(path);

            FullImcInfo info;

            if (exists)
            {
                info = await GetFullImcInfo(path, cachedIndexFile, cachedModList);
            }
            else
            {
                var ri = XivDependencyGraph.ExtractRootInfo(path);
                if (ri.SecondaryType == null)
                {
                    info = new FullImcInfo()
                    {
                        DefaultSubset = new List <XivImc>()
                        {
                            new XivImc(), new XivImc(), new XivImc(), new XivImc(), new XivImc()
                        },
                        SubsetList     = new List <List <XivImc> >(),
                        TypeIdentifier = ImcType.Set
                    };
                }
                else
                {
                    info = new FullImcInfo()
                    {
                        DefaultSubset = new List <XivImc>()
                        {
                            new XivImc()
                        },
                        SubsetList     = new List <List <XivImc> >(),
                        TypeIdentifier = ImcType.NonSet
                    };
                }
            }


            for (int i = 0; i < entries.Count; i++)
            {
                XivImc e;
                if (i >= info.SubsetCount + 1)
                {
                    e = new XivImc();
                }
                else
                {
                    e = info.GetEntry(i, slot);
                }
                e.Mask        = entries[i].Mask;
                e.Decal       = entries[i].Decal;
                e.Vfx         = entries[i].Vfx;
                e.Animation   = entries[i].Animation;
                e.MaterialSet = entries[i].MaterialSet;

                if (i >= info.SubsetCount + 1)
                {
                    info.SetEntry(e, i, slot, true);
                }
            }

            // Save the modified info.
            await SaveFullImcInfo(info, path, Constants.InternalModSourceName, referenceItem, cachedIndexFile, cachedModList);
        }