/// <summary> /// Get a FacetSector given an ID. FacetSector contains tile information about current block. /// UOPs related. /// </summary> /// <param name="sector"></param> /// <returns></returns> public static FacetSector getSector(int sector) { //Fast search if(facetSectors.ContainsKey(sector)) return facetSectors[sector]; int currentFacet = 0; //Look for the file in facet hashes string toHash = string.Format("build/sectors/facet_{0:D2}/{1:D8}.bin", currentFacet , sector); ulong hash = HashDictionary.HashFileName(toHash); if(!UOResourceManager.uopHashes.facet0Hashes.ContainsKey(hash)){ UOConsole.Fatal("Cannot find {0} in facet0Hashes", toHash); return null; } UOResourceManager.uopMapping_t map = UOResourceManager.uopHashes.facet0Hashes[hash]; MythicPackage _uop = new MythicPackage(fileDirectory + "facet0.uop"); byte[] raw = _uop.Blocks[map.block].Files[map.file].Unpack(_uop.FileInfo.FullName); FacetSector fs; using(MemoryStream ms = new MemoryStream(raw)){ using (BinaryReader r = new BinaryReader(ms)) { fs = FacetSector.readSector(r); } } facetSectors[sector] = fs; return fs; }
private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e) { e.Node.Nodes.Clear(); MythicPackage parent = (MythicPackage)e.Node.Tag; var myp = new MYP(); using (var stream = new FileStream(Path.Combine(frmBuilder.WarFolder,parent.ToString() + ".MYP"), FileMode.Open, FileAccess.Read)) { myp.Load(stream); List<TreeNode> nodes = new List<TreeNode>(); foreach (var key in myp.Files.Keys) { string name = key.ToString(); if (MYPHash.DeHash.ContainsKey(key)) name = MYPHash.DeHash[key]; TreeNode node = new TreeNode(name); node.Tag = myp.Files[key]; nodes.Add(node); } e.Node.Nodes.AddRange(nodes.OrderBy(x => x.Text).ToArray()); } }
/// <summary> /// Get the item image base on the provided filename /// </summary> /// <param name="fileName">Filename (contained inside the UOP)</param> /// <returns></returns> public Bitmap GetItemImage(string gamePath, bool useOldKRItems = false) { // open the uop file containing the item images MythicPackage UOPimgs = new MythicPackage(Path.Combine(gamePath, useOldKRItems ? "Texture.uop" : "LegacyTexture.uop")); // build the file name based on the type of items we want to see string fn = (useOldKRItems ? "build/worldart/" : "build/tileartlegacy/") + FileName; // search for the image file inside the UOP SearchResult sr = UOPimgs.SearchExactFileName(fn); // did we find the image? if (sr.Found) { // create the image using (DDSImage dds = new DDSImage(UOPimgs.Blocks[sr.Block].Files[sr.File].Unpack(UOPimgs.FileInfo.FullName))) { // store the image data return((Bitmap)dds.BitmapImage.Clone()); } } return(null); }
public UnpackArgs(MythicPackage p, MythicPackageBlock b) { m_Action = BLOCK; m_Package = p; m_Block = b; }
public UnpackArgs(MythicPackage p) { m_Action = PACKAGE; m_Package = p; }
public SaveMythicPackageArgs(MythicPackage package, string fileName) { m_Package = package; m_FileName = fileName; }
// -------------------------------------------------------------- #region CONSTRUCTOR // -------------------------------------------------------------- /// <summary> /// Initialize the thread arguments /// </summary> /// <param name="package">UOP file to save</param> /// <param name="fileName">destination file name to use</param> public SaveMythicPackageArgs(MythicPackage package, string fileName, bool closeFile = false) { Package = package; FileName = fileName; CloseFile = closeFile; }
//Preload all hashes public static bool loadUOPs() { //Load the string dictionary data MythicPackage sd = new MythicPackage(fileDirectory + "string_dictionary.uop"); byte[] data = sd.Blocks[0].Files[0].Unpack(sd.FileInfo.FullName); using (MemoryStream fs = new MemoryStream(data)) { using (BinaryReader r = new BinaryReader(fs)) { stringDictionary.unk64 = r.ReadUInt64(); stringDictionary.count = r.ReadUInt32(); stringDictionary.unk16 = r.ReadInt16(); stringDictionary.values = new string[stringDictionary.count]; for (int i = 0; i < stringDictionary.count; ++i) { ushort len = r.ReadUInt16(); byte[] datas = r.ReadBytes(len); stringDictionary.values[i] = UTF8Encoding.ASCII.GetString(datas); } } } //Load the map conversion between new ids and legacy ones using (FileStream fs = new FileStream(fileDirectory + "legacyterrainmap.csv", FileMode.Open)) { using (StreamReader r = new StreamReader(fs)) { string line = r.ReadLine(); //legacy newid newsub while (true) { line = r.ReadLine(); if (line == null) { break; } string[] values = line.Split(','); if (values.Length != 3) { UOConsole.Fatal("cannot read legacyterrainmap.csv"); return(false); } legacyTerrainMap[uint.Parse(values[0])] = new legacyTerrainMap_t(uint.Parse(values[0]), uint.Parse(values[1]), uint.Parse(values[2])); } } } //Now build files dictionaries for fast searching uopHashes.tileartHashes = new Dictionary <ulong, uopMapping_t>(); uopHashes.textureHashes = new Dictionary <ulong, uopMapping_t>(); uopHashes.terrainHashes = new Dictionary <ulong, uopMapping_t>(); uopHashes.facet0Hashes = new Dictionary <ulong, uopMapping_t>(); uopHashes.legacyTexturesHashes = new Dictionary <ulong, uopMapping_t>(); MythicPackage _uop = new MythicPackage(fileDirectory + "tileart.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.tileartHashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } _uop = new MythicPackage(fileDirectory + "Texture.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.textureHashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } _uop = new MythicPackage(fileDirectory + "TerrainDefinition.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.terrainHashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } _uop = new MythicPackage(fileDirectory + "facet0.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.facet0Hashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } _uop = new MythicPackage(fileDirectory + "LegacyTexture.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.legacyTexturesHashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } return(true); }
private void Worker_DoWork(object sender, DoWorkEventArgs e) { if (e.Argument is DictionaryArgs) { DictionaryArgs args = (DictionaryArgs)e.Argument; if (args.Load) { HashDictionary.LoadDictionary(args.Name); } else if (args.Save) { HashDictionary.SaveDictionary(args.Name); } else if (args.Merge) { HashDictionary.MergeDictionary(args.Name); } } else if (e.Argument is MythicLoadArgs) { MythicLoadArgs args = (MythicLoadArgs)e.Argument; MythicPackage[] packs = new MythicPackage[args.Names.Length]; for (int i = 0; i < args.Names.Length; i++) { packs[i] = MythicPackage.Read(args.Names[i]); } args.Result = packs; } else if (e.Argument is SpyProcessArgs) { SpyProcessArgs args = (SpyProcessArgs)e.Argument; m_Spy.Init(args.Process); m_Spy.MainLoop(); } else if (e.Argument is SpyPathArgs) { SpyPathArgs args = (SpyPathArgs)e.Argument; m_Spy.Init(args.Path); m_Spy.MainLoop(); } else if (e.Argument is UnpackArgs) { UnpackArgs args = (UnpackArgs)e.Argument; if (args.IsPackage) { args.Package.Decompress(UnpackArgs.Path, args.Package.Info.Name); } else if (args.IsBlock) { using (FileStream stream = File.OpenRead(args.Package.Info.FullName)) { using (BinaryReader reader = new BinaryReader(stream)) args.Block.Decompress(reader, UnpackArgs.Path, args.Package.Info.Name); } } else if (args.IsFile) { using (FileStream stream = File.OpenRead(args.Package.Info.FullName)) { using (BinaryReader reader = new BinaryReader(stream)) args.File.Decompress(reader, UnpackArgs.Path, String.Format("{0}_{1}", args.Package.Info.Name, args.Block.Index)); } } } else if (e.Argument is SearchArgs) { SearchArgs args = (SearchArgs)e.Argument; args.Found = 0; for (int i = args.From; i < args.To; i++) { if (SearchKeyword(String.Format("{0}{1}{2}", args.Before, i.ToString("D" + args.Length), args.After), true)) { args.Found += 1; } } } e.Result = e.Argument; }
private void Unpack_Click(object sender, EventArgs e) { if (Worker.IsBusy) { return; } if (UnpackArgs.Path == null) { if (SelectFolder.ShowDialog() == DialogResult.OK) { UnpackArgs.Path = SelectFolder.SelectedPath; } else { return; } } UnpackArgs args = null; MythicPackage p = null; MythicPackageBlock b = null; MythicPackageIndex idx = null; if (TreeView.SelectedNode != null) { if (TreeView.SelectedNode.Tag is MythicPackage) { p = (MythicPackage)TreeView.SelectedNode.Tag; if (ListBox.SelectedIndex == -1) { args = new UnpackArgs(p); } } else if (TreeView.SelectedNode.Tag is MythicPackageBlock) { p = (MythicPackage)TreeView.SelectedNode.Parent.Tag; b = (MythicPackageBlock)TreeView.SelectedNode.Tag; if (ListBox.SelectedIndex == -1) { args = new UnpackArgs(p, b); } } } if (ListBox.SelectedItem is MythicPackageIndex) { idx = (MythicPackageIndex)ListBox.SelectedItem; if (p != null && b != null) { args = new UnpackArgs(p, b, idx); } } if (args != null) { StatusLabel.Text = String.Format("Unpacking in {0}", UnpackArgs.Path); Unpack.Enabled = false; Worker.RunWorkerAsync(args); } }
//Preload all hashes public static bool loadUOPs(){ //Load the string dictionary data MythicPackage sd = new MythicPackage(fileDirectory + "string_dictionary.uop"); byte[] data = sd.Blocks[0].Files[0].Unpack(sd.FileInfo.FullName); using (MemoryStream fs = new MemoryStream(data)) { using (BinaryReader r = new BinaryReader(fs)) { stringDictionary.unk64 = r.ReadUInt64(); stringDictionary.count = r.ReadUInt32(); stringDictionary.unk16 = r.ReadInt16(); stringDictionary.values = new string[stringDictionary.count]; for (int i = 0; i < stringDictionary.count; ++i) { ushort len = r.ReadUInt16(); byte[] datas = r.ReadBytes(len); stringDictionary.values[i]= UTF8Encoding.ASCII.GetString(datas); } } } //Load the map conversion between new ids and legacy ones using (FileStream fs = new FileStream(fileDirectory + "legacyterrainmap.csv", FileMode.Open)) { using (StreamReader r = new StreamReader(fs)) { string line = r.ReadLine();//legacy newid newsub while(true) { line = r.ReadLine(); if(line == null) break; string[] values = line.Split(','); if(values.Length != 3){ UOConsole.Fatal("cannot read legacyterrainmap.csv"); return false; } legacyTerrainMap[uint.Parse(values[0])] = new legacyTerrainMap_t(uint.Parse(values[0]), uint.Parse(values[1]), uint.Parse(values[2])); } } } //Now build files dictionaries for fast searching uopHashes.tileartHashes = new Dictionary<ulong, uopMapping_t>(); uopHashes.textureHashes = new Dictionary<ulong, uopMapping_t>(); uopHashes.terrainHashes = new Dictionary<ulong, uopMapping_t>(); uopHashes.facet0Hashes = new Dictionary<ulong, uopMapping_t>(); uopHashes.legacyTexturesHashes = new Dictionary<ulong, uopMapping_t>(); MythicPackage _uop = new MythicPackage(fileDirectory + "tileart.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.tileartHashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } _uop = new MythicPackage(fileDirectory + "Texture.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.textureHashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } _uop = new MythicPackage(fileDirectory + "TerrainDefinition.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.terrainHashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } _uop = new MythicPackage(fileDirectory + "facet0.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.facet0Hashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } _uop = new MythicPackage(fileDirectory + "LegacyTexture.uop"); for (int i = 0; i < _uop.Blocks.Count; ++i) { for (int j = 0; j < _uop.Blocks[i].Files.Count; ++j) { uopHashes.legacyTexturesHashes.Add(_uop.Blocks[i].Files[j].FileHash, new uopMapping_t(i, j)); } } return true; }
//Get a tileart given a graphic id public static Tileart getTileart(uint graphic) { //Fast search if (tileartCollection.ContainsKey(graphic)) { return tileartCollection[graphic]; } //Get the file from tileart using the id ulong hash = HashDictionary.HashFileName(string.Format("build/tileart/{0:D8}.bin", graphic)); if (!uopHashes.tileartHashes.ContainsKey(hash)) { UOConsole.Fatal("Cannot find {0} in tileartHashes", graphic); return null; } uopMapping_t pos = uopHashes.tileartHashes[hash]; MythicPackage _uop = new MythicPackage(fileDirectory + "tileart.uop"); byte[] raw = _uop.Blocks[pos.block].Files[pos.file].Unpack(_uop.FileInfo.FullName); //Read the loaded tileart file. Tileart t; using (MemoryStream ms = new MemoryStream(raw)) { using (BinaryReader r = new BinaryReader(ms)) { t = Tileart.readTileart(r); } } if (t == null) { UOConsole.Fatal("Cannot read tileart file"); return t; } tileartCollection[graphic] = t; //Returns the texture according to subtype return t; }
//Land tiles does not have tileart TEXTURES section.. we need to extract them from terrain definition public static TextureImageInfo getLandtileTextureID(uint legacyLandtileID){ //Fast search if(landtiles.ContainsKey(legacyLandtileID)){ return landtiles[legacyLandtileID]; } //Translate the legacy ID to the new pair newID-subtype using legacyterrainMap if (!legacyTerrainMap.ContainsKey(legacyLandtileID)) { UOConsole.Fatal("Cannot find {0} in legacyTerrainMap", legacyLandtileID); return null; } legacyTerrainMap_t landtileID = legacyTerrainMap[legacyLandtileID]; //Get the file from terrain definition using the newID ulong hash = HashDictionary.HashFileName(string.Format("build/terraindefinition/{0}.bin", landtileID.newID)); if (!uopHashes.terrainHashes.ContainsKey(hash)) { UOConsole.Fatal("Cannot find {0} in terrainHashes", landtileID.newID); return null; } uopMapping_t pos = uopHashes.terrainHashes[hash]; MythicPackage _uop = new MythicPackage(fileDirectory + "TerrainDefinition.uop"); byte[] raw = _uop.Blocks[pos.block].Files[pos.file].Unpack(_uop.FileInfo.FullName); //Read the loaded terrainDefinition file. TerrainDefinition td; using (MemoryStream ms = new MemoryStream(raw)) { using (BinaryReader r = new BinaryReader(ms)) { td = TerrainDefinition.readTerrainDefinition(r); } } if (td == null){ UOConsole.Fatal("Cannot read terrainDefinition file"); return null; } landtiles[legacyLandtileID] = td.textures.texturesArray[landtileID.newSubtype]; //Returns the texture according to subtype return td.textures.texturesArray[landtileID.newSubtype]; }
public static UOResource getLegacyResource(TextureImageInfo tileartTextureInfo) { //FAST search if (legacyTextures.ContainsKey(tileartTextureInfo.textureIDX)) { //TODO: references++ return legacyTextures[tileartTextureInfo.textureIDX]; } //Get the string from stringDictionary if (tileartTextureInfo.textureIDX >= stringDictionary.count) { UOConsole.Fatal("String {0} not found in dictionary.", tileartTextureInfo.textureIDX); return null; } string tga = stringDictionary.values[tileartTextureInfo.textureIDX]; //Replace extension int start = (tga.LastIndexOf("\\") == -1) ? 0 : (tga.LastIndexOf("\\") + 1); int end = tga.IndexOf("_"); if (end == -1) { UOConsole.Fatal("no descr in: {0} .. trying with extension", tga); tga = tga.Replace(".tga", ""); end = tga.Length; } //UOConsole.Fatal("{0} {1} {2}", tga, start, end); string toHash = tga.Substring(start, end - start); while(toHash.Length < 8)//Filling the missing zeros toHash = "0" + toHash; toHash += ".dds"; toHash = toHash.ToLower(); toHash = "build/tileartlegacy/" + toHash; //Get the file from Texture.uop ulong tehHash = HashDictionary.HashFileName(toHash); if (!uopHashes.legacyTexturesHashes.ContainsKey(tehHash)) { UOConsole.Fatal("string {0} not found in legacyTextureHashes - tga: {1}", toHash, tga); return null; } uopMapping_t map = uopHashes.legacyTexturesHashes[tehHash]; MythicPackage tex = new MythicPackage(fileDirectory + "LegacyTexture.uop"); byte[] raw = tex.Blocks[map.block].Files[map.file].Unpack(tex.FileInfo.FullName); UOResource res = new UOResource(raw, ShaderTypes.Sprite, true); legacyTextures.Add(tileartTextureInfo.textureIDX, res); return res; }
//--------------------------------- public void ConvertMap() { Log("Loading map into memory.", true); tileMatrix.PreLoadMap(task_mapstatics, ProgressSetMax, ProgressSetVal, Log); Log("\nMap loaded!\n", true); int totBlocks = (width / 64) * (height / 64); ProgressSetMax(totBlocks); Log("Conversion started.", true); try { //WriteMapResolution(); //-From my experience, we don't need this file, even if we create a facet UOP without this it will work fine. //-Moreover, we don't have the real name of this file, so we can't repack it. When i'll find out this name i'll uncomment the line (and fix the output name). //for (int blocksX = 0; blocksX < (tileMatrix.Width / 64); blocksX++) Parallel.For(0, (tileMatrix.Width / 64), blocksX => { for (int blocksY = 0; blocksY < (tileMatrix.Height / 64); blocksY++) { WriteMapBlock(blocksX, blocksY, ((blocksX * 64) + blocksY)); //tileMatrix.DisposeMapBlock(blocksX, blocksY); // I can't dispose the map block because i may need a different block from the current when writing delimiters } }); } catch (Exception e) // (ThreadAbortException e) { Log(String.Format("\nConversion ERROR: ABORTING. Message: {0}", e.Message), true); SetItemsState(true); ProgressSetVal(0); return; } finally { Log("\nConversion ended successifully!", true); } //Saving memory if (task_dds) { radarcol = null; } tileMatrix.Dispose(); GC.Collect(); //needed, otherwise it won't readily free the memory GC.WaitForPendingFinalizers(); if (task_uop) { ProgressSetVal(0); ProgressSetMax(totBlocks); MythicPackage package = new MythicPackage(5); Log("\nStarting to pack the files into the .uop package... ", true); try { for (int i = 0; i < totBlocks; i++) { string binFileName = binPath + string.Format("{0:D8}.bin", i); package.AddFile(binFileName, string.Format("build/sectors/facet_0{0}/", mapIndex), CompressionFlag.Zlib); ProgressIncrease(); } package.Save(outPath + string.Format("facet{0}.uop", mapIndex)); } catch (System.IO.IOException e) { Log(String.Format("\nUop packing ERROR: skipping. Message: {0}", e.Message), true); File.Delete(outPath + string.Format("facet{0}.uop", mapIndex)); } finally { Log("Done!", true); } //Saving memory for (int i = 0; i < package.Blocks.Count; i++) { package.RemoveBlock(i); } package = null; //GC.Collect(); //GC.WaitForPendingFinalizers(); Log("\nRemoving .bin temporary files... ", true); try { Directory.Delete(outPath + "build", true); } catch (System.IO.IOException e) { Log(String.Format("\nRemoving .bin temporary files ERROR: skipping. Message: {0}", e.Message), true); } finally { Log("Done!", true); } } if (task_dds) { Log("\nStarting to render the dds image... ", true); ProgressSetMarquee(true); try { // Unlock the bits. unsafe { bmpPtr = null; } bmp.UnlockBits(bmpData); /* * MemoryStream bmpStream = new MemoryStream(); * bmp.Save(bmpStream, ImageFormat.Bmp); * byte[] bmpArray = bmpStream.ToArray(); */ ImageConverter converter = new ImageConverter(); byte[] bmpArray = (byte[])converter.ConvertTo(bmp, typeof(byte[])); bmp.Dispose(); using (MagickImage bmpMagick = new MagickImage(bmpArray)) { bmpMagick.Format = MagickFormat.Dds; bmpMagick.Settings.SetDefine(MagickFormat.Dds, "compression", "dxt1"); // convert to a DXT1 DDS using (FileStream fileS = File.Create(outPath + string.Format("facet0{0}.dds", mapIndex))) { bmpMagick.Write(fileS); } } Log("Done!", true); //Saving memory GC.Collect(); GC.WaitForPendingFinalizers(); } catch (Exception e) //(System.IO.IOException e) { Log(String.Format("\nDDS rendering ERROR: skipping. Message: {0}", e.Message), true); File.Delete(outPath + string.Format("facet0{0}.dds", mapIndex)); } ProgressSetMarquee(false); } if (!task_uop) { Log(string.Format("\nSuccess!\n" + "Generated files are raw .bin binary files, " + "you need to repack them using Mythic Package Editor.\n" + "Remember, you should use zlib compression and add the files " + "with the directory tree (\"build/sectors/facet_0{0}/\".\n" + "Then, you can pack it all into facet{0}.uop\n\n", mapIndex), true); } else { Log("\nSuccess!\n", true); } Success(); }