Esempio n. 1
0
        /// <summary>
        /// Writes the newly imported data to the .dat for modifications.
        /// </summary>
        /// <param name="data">The data to be written.</param>
        /// <param name="modEntry">The modlist entry (if any) for the given file.</param>
        /// <param name="inModList">Is the item already contained within the mod list.</param>
        /// <param name="internalFilePath">The internal file path of the item being modified.</param>
        /// <param name="category">The category of the item.</param>
        /// <param name="itemName">The name of the item being modified.</param>
        /// <param name="lineNum">The line number of the existing mod list entry for the item if it exists.</param>
        /// <returns>The new offset in which the modified data was placed.</returns>
        public static int WriteToDat(List <byte> data, JsonEntry modEntry, bool inModList, string internalFilePath, string category, string itemName, int lineNum, string datName)
        {
            int  offset          = 0;
            bool dataOverwritten = false;

            var datNum = int.Parse(Info.ModDatDict[datName]);

            var modDatPath = string.Format(Info.datDir, datName, datNum);

            if (inModList)
            {
                datNum     = ((modEntry.modOffset / 8) & 0x0F) / 2;
                modDatPath = string.Format(Info.datDir, modEntry.datFile, datNum);
            }
            else
            {
                var fileLength = new FileInfo(modDatPath).Length;
                while (fileLength >= 2000000000)
                {
                    datNum    += 1;
                    modDatPath = string.Format(Info.datDir, datName, datNum);
                    if (!File.Exists(modDatPath))
                    {
                        CreateDat.MakeNewDat(datName);
                    }
                    fileLength = new FileInfo(modDatPath).Length;
                }
            }

            var datOffsetAmount = 16 * datNum;


            if (inModList)
            {
                if (modEntry.modOffset == 0)
                {
                    FlexibleMessageBox.Show("TexTools detected a Mod List entry with a Mod Offset of 0.\n\n" +
                                            "Please submit a bug report along with your modlist file.", "ImportTex Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(0);
                }
                else if (modEntry.originalOffset == 0)
                {
                    FlexibleMessageBox.Show("TexTools detected a Mod List entry with an Original Offset of 0.\n\n" +
                                            "Please submit a bug report along with your modlist file.", "ImportTex Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(0);
                }
            }

            try
            {
                using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(modDatPath)))
                {
                    /*
                     * If the item has been previously modified and the compressed data being imported is smaller or equal to the exisiting data
                     *  replace the existing data with new data.
                     */
                    if (inModList && data.Count <= modEntry.modSize)
                    {
                        if (modEntry.modOffset != 0)
                        {
                            int sizeDiff = modEntry.modSize - data.Count;

                            bw.BaseStream.Seek(modEntry.modOffset - datOffsetAmount, SeekOrigin.Begin);

                            bw.Write(data.ToArray());

                            bw.Write(new byte[sizeDiff]);

                            Helper.UpdateIndex(modEntry.modOffset, internalFilePath, datName);
                            Helper.UpdateIndex2(modEntry.modOffset, internalFilePath, datName);

                            offset = modEntry.modOffset;

                            dataOverwritten = true;
                        }
                    }
                    else
                    {
                        int emptyLength = 0;
                        int emptyLine   = 0;

                        /*
                         * If there is an empty entry in the modlist and the compressed data being imported is smaller or equal to the available space
                         *  write the compressed data in the existing space.
                         */
                        try
                        {
                            foreach (string line in File.ReadAllLines(Properties.Settings.Default.Modlist_Directory))
                            {
                                JsonEntry emptyEntry = JsonConvert.DeserializeObject <JsonEntry>(line);

                                if (emptyEntry.fullPath.Equals("") && emptyEntry.datFile.Equals(datName))
                                {
                                    if (emptyEntry.modOffset != 0)
                                    {
                                        emptyLength = emptyEntry.modSize;

                                        if (emptyLength > data.Count)
                                        {
                                            int sizeDiff = emptyLength - data.Count;

                                            bw.BaseStream.Seek(emptyEntry.modOffset - datOffsetAmount, SeekOrigin.Begin);

                                            bw.Write(data.ToArray());

                                            bw.Write(new byte[sizeDiff]);

                                            int originalOffset = Helper.UpdateIndex(emptyEntry.modOffset, internalFilePath, datName) * 8;
                                            Helper.UpdateIndex2(emptyEntry.modOffset, internalFilePath, datName);

                                            if (inModList)
                                            {
                                                originalOffset = modEntry.originalOffset;

                                                JsonEntry replaceOriginalEntry = new JsonEntry()
                                                {
                                                    category       = String.Empty,
                                                    name           = "Empty Replacement",
                                                    fullPath       = String.Empty,
                                                    originalOffset = 0,
                                                    modOffset      = modEntry.modOffset,
                                                    modSize        = modEntry.modSize,
                                                    datFile        = datName
                                                };

                                                string[] oLines = File.ReadAllLines(Properties.Settings.Default.Modlist_Directory);
                                                oLines[lineNum] = JsonConvert.SerializeObject(replaceOriginalEntry);
                                                File.WriteAllLines(Properties.Settings.Default.Modlist_Directory, oLines);
                                            }


                                            JsonEntry replaceEntry = new JsonEntry()
                                            {
                                                category       = category,
                                                name           = itemName,
                                                fullPath       = internalFilePath,
                                                originalOffset = originalOffset,
                                                modOffset      = emptyEntry.modOffset,
                                                modSize        = emptyEntry.modSize,
                                                datFile        = datName
                                            };

                                            string[] lines = File.ReadAllLines(Properties.Settings.Default.Modlist_Directory);
                                            lines[emptyLine] = JsonConvert.SerializeObject(replaceEntry);
                                            File.WriteAllLines(Properties.Settings.Default.Modlist_Directory, lines);

                                            offset = emptyEntry.modOffset;

                                            dataOverwritten = true;
                                            break;
                                        }
                                    }
                                }
                                emptyLine++;
                            }
                        }
                        catch (Exception ex)
                        {
                            FlexibleMessageBox.Show("Error Accessing .modlist File \n" + ex.Message, "ImportTex Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        if (!dataOverwritten)
                        {
                            bw.BaseStream.Seek(0, SeekOrigin.End);

                            while ((bw.BaseStream.Position & 0xFF) != 0)
                            {
                                bw.Write((byte)0);
                            }

                            int eof = (int)bw.BaseStream.Position + data.Count;

                            while ((eof & 0xFF) != 0)
                            {
                                data.AddRange(new byte[16]);
                                eof = eof + 16;
                            }

                            offset = (int)bw.BaseStream.Position + datOffsetAmount;

                            if (offset != 0)
                            {
                                bw.Write(data.ToArray());
                            }
                            else
                            {
                                FlexibleMessageBox.Show("There was an issue obtaining the .dat4 offset to write data to, try importing again. " +
                                                        "\n\n If the problem persists, please submit a bug report.", "ImportTex Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                FlexibleMessageBox.Show("Error Accessing .dat4 File \n" + ex.Message, "ImportTex Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return(0);
            }


            if (!dataOverwritten)
            {
                if (offset != 0)
                {
                    int oldOffset = Helper.UpdateIndex(offset, internalFilePath, datName) * 8;
                    Helper.UpdateIndex2(offset, internalFilePath, datName);

                    /*
                     * If the item has been previously modifed, but the new compressed data to be imported is larger than the existing data
                     * remove the data from the modlist, leaving the offset and size intact for future use
                     */
                    if (inModList && data.Count > modEntry.modSize && modEntry != null)
                    {
                        oldOffset = modEntry.originalOffset;

                        JsonEntry replaceEntry = new JsonEntry()
                        {
                            category       = String.Empty,
                            name           = String.Empty,
                            fullPath       = String.Empty,
                            originalOffset = 0,
                            modOffset      = modEntry.modOffset,
                            modSize        = modEntry.modSize,
                            datFile        = datName
                        };

                        string[] lines = File.ReadAllLines(Properties.Settings.Default.Modlist_Directory);
                        lines[lineNum] = JsonConvert.SerializeObject(replaceEntry);
                        File.WriteAllLines(Properties.Settings.Default.Modlist_Directory, lines);
                    }

                    JsonEntry entry = new JsonEntry()
                    {
                        category       = category,
                        name           = itemName,
                        fullPath       = internalFilePath,
                        originalOffset = oldOffset,
                        modOffset      = offset,
                        modSize        = data.Count,
                        datFile        = datName
                    };

                    try
                    {
                        using (StreamWriter modFile = new StreamWriter(Properties.Settings.Default.Modlist_Directory, true))
                        {
                            modFile.BaseStream.Seek(0, SeekOrigin.End);
                            modFile.WriteLine(JsonConvert.SerializeObject(entry));
                        }
                    }
                    catch (Exception ex)
                    {
                        FlexibleMessageBox.Show("Error Accessing .modlist File \n" + ex.Message, "ImportTex Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }

            return(offset);
        }
Esempio n. 2
0
        private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            var backgroundWorker = sender as BackgroundWorker;

            var   packListCount = packList.Count;
            float i             = 0;

            List <string> modFileLines = new List <string>(File.ReadAllLines(Properties.Settings.Default.Modlist_Directory));

            try
            {
                using (ZipArchive archive = ZipFile.OpenRead(packPath))
                {
                    backgroundWorker.ReportProgress(0, "Opening TTMP Data File...\n");

                    foreach (var entry in archive.Entries)
                    {
                        if (entry.FullName.EndsWith(".mpd"))
                        {
                            var  stream        = entry.Open();
                            var  remainingPack = packListCount;
                            var  currentPack   = 0;
                            var  prevPack      = 0;
                            long newOffset     = 0;
                            long offsetSum     = 0;
                            List <ModPackItems> pack;
                            long cursor = 0;

                            while (currentPack != packListCount)
                            {
                                prevPack = currentPack;
                                if (remainingPack > 100)
                                {
                                    pack           = packList.GetRange(currentPack, 100);
                                    currentPack   += 100;
                                    remainingPack -= 100;
                                }
                                else
                                {
                                    pack         = packList.GetRange(currentPack, remainingPack);
                                    currentPack += remainingPack;
                                }

                                backgroundWorker.ReportProgress((int)((i / packListCount) * 100), $"\nReading Entries ({prevPack} - {currentPack}/{packListCount})\n\n");

                                long totalSize    = 0;
                                var  modPackBytes = new List <byte>();
                                foreach (var p in pack)
                                {
                                    if (p.mEntry.ModOffset < cursor)
                                    {
                                        backgroundWorker.ReportProgress((int)((i / packListCount) * 100), $"There was an warning in importing. \nImproper Mod Offset in ModPack for {p.mEntry.Name}. \nUnable to import {p.mEntry.Name}.");
                                        continue;
                                    }
                                    totalSize += p.mEntry.ModSize;
                                    var buf = new byte[p.mEntry.ModSize];
                                    while (p.mEntry.ModOffset > cursor)
                                    {
                                        cursor++;
                                        stream.ReadByte(); //seek forward for next offset
                                    }
                                    stream.Read(buf, 0, buf.Length);
                                    cursor += buf.Length;
                                    modPackBytes.AddRange(buf);
                                }
                                var uncompBytes = modPackBytes.ToArray();

                                offsetSum += newOffset;
                                newOffset  = totalSize;

                                using (var ms = new MemoryStream(uncompBytes))
                                {
                                    //backgroundWorker.ReportProgress((int)((i / packListCount) * 100), "Reading TTMP Data...\n");
                                    var dataOffset = 0;
                                    using (var br = new BinaryReader(ms))
                                    {
                                        //backgroundWorker.ReportProgress((int)((i / packListCount) * 100), "Begining Import...\n");

                                        foreach (var mpi in pack)
                                        {
                                            currentImport = mpi.Name + "....";
                                            backgroundWorker.ReportProgress((int)((i / packListCount) * 100), currentImport);

                                            JsonEntry modEntry       = null;
                                            bool      inModList      = false;
                                            bool      overwrite      = false;
                                            int       lineNum        = 0;
                                            int       originalOffset = 0;
                                            int       offset         = 0;

                                            byte[]      dataBytes   = new byte[mpi.mEntry.ModSize];
                                            List <byte> modDataList = new List <byte>();

                                            br.BaseStream.Seek(dataOffset, SeekOrigin.Begin);
                                            modDataList.AddRange(br.ReadBytes(mpi.mEntry.ModSize));

                                            try
                                            {
                                                foreach (var line in modFileLines)
                                                {
                                                    modEntry = JsonConvert.DeserializeObject <JsonEntry>(line);
                                                    if (modEntry.fullPath.Equals(mpi.mEntry.FullPath))
                                                    {
                                                        inModList = true;
                                                        break;
                                                    }
                                                    lineNum++;
                                                }



                                                var datNum = int.Parse(Info.ModDatDict[mpi.mEntry.DatFile]);

                                                var modDatPath = string.Format(Info.datDir, mpi.mEntry.DatFile, datNum);

                                                var fileLength = new FileInfo(modDatPath).Length;
                                                while (fileLength + mpi.mEntry.ModSize >= 2000000000)
                                                {
                                                    datNum    += 1;
                                                    modDatPath = string.Format(Info.datDir, mpi.mEntry.DatFile, datNum);
                                                    if (!File.Exists(modDatPath))
                                                    {
                                                        CreateDat.MakeNewDat(mpi.mEntry.DatFile);
                                                    }
                                                    fileLength = new FileInfo(modDatPath).Length;
                                                }

                                                //is in modlist and size of new mod is less than or equal to existing mod size
                                                if (inModList && mpi.mEntry.ModSize <= modEntry.modSize)
                                                {
                                                    int sizeDiff = modEntry.modSize - modDataList.Count;

                                                    datNum     = ((modEntry.modOffset / 8) & 0x0F) / 2;
                                                    modDatPath = string.Format(Info.datDir, modEntry.datFile, datNum);
                                                    var datOffsetAmount = 16 * datNum;

                                                    using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(modDatPath)))
                                                    {
                                                        bw.BaseStream.Seek(modEntry.modOffset - datOffsetAmount, SeekOrigin.Begin);

                                                        bw.Write(modDataList.ToArray());

                                                        bw.Write(new byte[sizeDiff]);
                                                    }

                                                    Helper.UpdateIndex(modEntry.modOffset, mpi.mEntry.FullPath, mpi.mEntry.DatFile);
                                                    Helper.UpdateIndex2(modEntry.modOffset, mpi.mEntry.FullPath, mpi.mEntry.DatFile);

                                                    offset = modEntry.modOffset;

                                                    overwrite = true;
                                                }

                                                if (!overwrite)
                                                {
                                                    using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(modDatPath)))
                                                    {
                                                        bw.BaseStream.Seek(0, SeekOrigin.End);

                                                        while ((bw.BaseStream.Position & 0xFF) != 0)
                                                        {
                                                            bw.Write((byte)0);
                                                        }

                                                        int eof = (int)bw.BaseStream.Position + modDataList.Count;

                                                        while ((eof & 0xFF) != 0)
                                                        {
                                                            modDataList.AddRange(new byte[16]);
                                                            eof = eof + 16;
                                                        }

                                                        var datOffsetAmount = 16 * datNum;
                                                        offset = (int)bw.BaseStream.Position + datOffsetAmount;

                                                        if (offset != 0)
                                                        {
                                                            bw.Write(modDataList.ToArray());
                                                        }
                                                        else
                                                        {
                                                            FlexibleMessageBox.Show("There was an issue obtaining the .dat4 offset to write data to, try importing again. " +
                                                                                    "\n\n If the problem persists, please submit a bug report.", "ImportModel Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                                                            return;
                                                        }
                                                    }

                                                    int oldOffset = Helper.UpdateIndex(offset, mpi.mEntry.FullPath, mpi.mEntry.DatFile) * 8;
                                                    Helper.UpdateIndex2(offset, mpi.mEntry.FullPath, mpi.mEntry.DatFile);

                                                    //is in modlist and size of new mod is larger than existing mod size
                                                    if (inModList && mpi.mEntry.ModSize > modEntry.modSize)
                                                    {
                                                        oldOffset = modEntry.originalOffset;

                                                        JsonEntry replaceEntry = new JsonEntry()
                                                        {
                                                            category       = String.Empty,
                                                            name           = String.Empty,
                                                            fullPath       = String.Empty,
                                                            originalOffset = 0,
                                                            modOffset      = modEntry.modOffset,
                                                            modSize        = modEntry.modSize,
                                                            datFile        = mpi.mEntry.DatFile
                                                        };


                                                        modFileLines[lineNum] = JsonConvert.SerializeObject(replaceEntry);
                                                        File.WriteAllLines(Properties.Settings.Default.Modlist_Directory, modFileLines);
                                                    }

                                                    JsonEntry jsonEntry = new JsonEntry()
                                                    {
                                                        category       = mpi.Category,
                                                        name           = mpi.Name,
                                                        fullPath       = mpi.mEntry.FullPath,
                                                        originalOffset = oldOffset,
                                                        modOffset      = offset,
                                                        modSize        = mpi.mEntry.ModSize,
                                                        datFile        = mpi.mEntry.DatFile
                                                    };

                                                    try
                                                    {
                                                        modFileLines.Add(JsonConvert.SerializeObject(jsonEntry));
                                                        File.WriteAllLines(Properties.Settings.Default.Modlist_Directory, modFileLines);
                                                    }
                                                    catch (Exception ex)
                                                    {
                                                        FlexibleMessageBox.Show("Error Accessing .modlist File \n" + ex.Message, "ImportModel Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                                                    }
                                                }
                                            }
                                            catch (Exception ex)
                                            {
                                                FlexibleMessageBox.Show("There was an error in importing. \n" + ex.Message, "ImportModPack Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                                                Debug.WriteLine(ex.StackTrace);
                                            }

                                            i++;

                                            backgroundWorker.ReportProgress((int)((i / packListCount) * 100), "Done.");

                                            dataOffset += mpi.mEntry.ModSize;
                                        }
                                    }
                                }
                            }
                            stream.Dispose();
                            stream.Close();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                FlexibleMessageBox.Show("Error opening TexTools ModPack file. \n" + ex.Message, "ImportModPack Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error);
                Debug.WriteLine(ex.StackTrace);
            }
        }