public RootHandler() { GlobalRoot = new RootChunk() { ContentFlags = ContentFlags.None, LocaleFlags = LocaleFlags.All_WoW }; encodingMap = new EncodingMap(EncodingType.ZLib, 9); }
public void SetArea(Vector3I start, Vector3I end, BlockVoxel voxel) { GetAreaFromPoints(start, end, out Vector3I areaStart, out Vector3I areaScale); RootChunk.TraverseToChunk(areaStart, true, out var startChunk); RootChunk.TraverseToChunk(areaStart + areaScale, true, out var endChunk); int chunkSideLength = RootChunk.SideLength; Vector3I wholeChunkArea = Vector3I.One + ((endChunk.Offset - startChunk.Offset) / chunkSideLength); Chunk <BlockVoxel>[,,] chunkCache = new Chunk <BlockVoxel> [ wholeChunkArea.X, wholeChunkArea.Y, wholeChunkArea.Z]; chunkCache[0, 0, 0] = startChunk; chunkCache[chunkCache.GetLength(0) - 1, chunkCache.GetLength(1) - 1, chunkCache.GetLength(2) - 1] = endChunk; Chunk <BlockVoxel> currentChunk; for (int x = 0; x < areaScale.X; x++) { for (int y = 0; y < areaScale.Y; y++) { for (int z = 0; z < areaScale.Z; z++) { Vector3I offset = new Vector3I(x, y, z); Vector3I cacheOffset = ((areaStart - startChunk.Offset) + offset) / chunkSideLength; if (chunkCache[cacheOffset.X, cacheOffset.Y, cacheOffset.Z] == null) { RootChunk.TraverseToChunk(areaStart + offset, true, out chunkCache[cacheOffset.X, cacheOffset.Y, cacheOffset.Z]); } currentChunk = chunkCache[cacheOffset.X, cacheOffset.Y, cacheOffset.Z]; if (currentChunk.Availability != ChunkAvailability.None) { currentChunk.Unlock(); currentChunk.SetVoxel(areaStart + offset - currentChunk.Offset, voxel); } } } } }
private bool IsBlockSolid(Vector3 position) { if (RootChunk.TraverseToChunk((Vector3I)position, false, out var chunk)) { if (chunk.TryGetVoxel(position - chunk.Offset, out var voxel, false)) { var voxelBlock = Blocks.GetBlock(voxel.BlockKey); return(voxelBlock.Properties.Type == BlockColliderType.Solid); } else { return(false); } }
public RootHandler(Stream data, LocaleFlags locale, uint minimumid = 0) { this.minimumId = minimumid; this.locale = locale; BinaryReader stream = new BinaryReader(data); long length = stream.BaseStream.Length; while (stream.BaseStream.Position < length) { RootChunk chunk = new RootChunk() { Count = stream.ReadUInt32(), ContentFlags = (ContentFlags)stream.ReadUInt32(), LocaleFlags = (LocaleFlags)stream.ReadUInt32(), }; // set the global root if (chunk.LocaleFlags == LocaleFlags.All_WoW && chunk.ContentFlags == ContentFlags.None) { GlobalRoot = chunk; } uint fileDataIndex = 0; for (int i = 0; i < chunk.Count; i++) { uint offset = stream.ReadUInt32(); RootEntry entry = new RootEntry() { FileDataIdOffset = offset, FileDataId = fileDataIndex + offset }; fileDataIndex = entry.FileDataId + 1; chunk.Entries.Add(entry); } foreach (var entry in chunk.Entries) { entry.CEKey = new MD5Hash(stream); entry.NameHash = stream.ReadUInt64(); maxId = Math.Max(maxId, entry.FileDataId); } Chunks.Add(chunk); } if (GlobalRoot == null) { CASContainer.Logger.LogCritical($"No Global root found. Root file is corrupt."); return; } // set maxid from cache maxId = Math.Max(Math.Max(maxId, minimumid), CASContainer.Settings.Cache?.MaxId ?? 0); // store encoding map encodingMap = (data as BLTEStream)?.EncodingMap.FirstOrDefault() ?? new EncodingMap(EncodingType.ZLib, 9); stream?.Dispose(); data?.Dispose(); }
private void SaveInternal(eSaveMode xiSaveMode, string xiFilename) { if (RootChunk == null) { MessageBox.Show("Can't save: no file is open"); return; } string lExceptionWhen = "saving file"; try { long lPreviousSize = -1; if (xiSaveMode == eSaveMode.Binary && File.Exists(xiFilename)) { lPreviousSize = new FileInfo(xiFilename).Length; } using (FileStream fs = File.Create(xiFilename)) { lExceptionWhen = "serialising the file"; if (xiSaveMode == eSaveMode.Binary) { if (RootChunk is VersionList) { CurrentLevel.Serialise(fs); } else { RootChunk.Serialise(fs); } } else if (xiSaveMode == eSaveMode.Xml) { XmlSerializer xs = new XmlSerializer(typeof(Chunk)); if (RootChunk is VersionList) { xs.Serialize(fs, CurrentLevel); } else { xs.Serialize(fs, RootChunk); } } else if (xiSaveMode == eSaveMode.Mmv) { if (RootChunk is VersionList) { VersionList lVersionList = (VersionList)RootChunk; lVersionList.AddLevel(CurrentLevel); RecursiveAddChunkNode(ChunkTreeView.Nodes[0].Nodes, 1, lVersionList.GetLastVersion()); } else if (RootChunk is Level) { VersionList lVersionList = new VersionList( (Level)RootChunk, Path.GetFileNameWithoutExtension(xiFilename), null); RootChunk = lVersionList; } RootChunk.Serialise(fs); } } if (lPreviousSize != -1 && lPreviousSize != new FileInfo(xiFilename).Length) { MessageBox.Show("WARNING: The size of your level has changed. Please check it's not too large, and check MMEd for bugs that have allowed the size to change.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } catch (Exception err) { Trace.WriteLine(err); MessageBox.Show(string.Format("Exception occurred while {0}: {1}", lExceptionWhen, err.Message), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } mLocalSettings.LastSavedFile = xiFilename; mLocalSettings.LastSavedMode = xiSaveMode; mCurrentFile = xiFilename; mCurrentFileMode = xiSaveMode; }
public RootHandler(Stream data, LocaleFlags locale, uint minimumid = 0, bool onlineListfile = false) { this.minimumId = minimumid; this.locale = locale; string cdnPath = Helper.GetCDNPath("listfile.csv"); if (!(File.Exists(Path.Combine(CASContainer.Settings.OutputPath, cdnPath))) && onlineListfile) { CASContainer.Logger.LogInformation("Downloading listfile from WoW.Tools"); ListFileClient.DownloadFile("https://wow.tools/casc/listfile/download/csv/unverified", cdnPath); } BinaryReader stream = new BinaryReader(data); // 8.2 root change int magic = stream.ReadInt32(); bool newFormat = magic == headerMagic; if (newFormat) { allFiles = stream.ReadInt32(); namedFiles = stream.ReadInt32(); } else { stream.BaseStream.Position = 0; } long length = stream.BaseStream.Length; while (stream.BaseStream.Position < length) { RootChunk chunk = new RootChunk() { Count = stream.ReadUInt32(), ContentFlags = (ContentFlags)stream.ReadUInt32(), LocaleFlags = (LocaleFlags)stream.ReadUInt32(), }; parsedFiles += (int)chunk.Count; // set the global root if (chunk.LocaleFlags == LocaleFlags.All_WoW && chunk.ContentFlags == ContentFlags.None) { GlobalRoot = chunk; } uint fileDataIndex = 0; for (int i = 0; i < chunk.Count; i++) { uint offset = stream.ReadUInt32(); RootEntry entry = new RootEntry() { FileDataIdOffset = offset, FileDataId = fileDataIndex + offset }; fileDataIndex = entry.FileDataId + 1; chunk.Entries.Add(entry); } if (newFormat) { foreach (var entry in chunk.Entries) { entry.CEKey = new MD5Hash(stream); maxId = Math.Max(maxId, entry.FileDataId); } if (parsedFiles > allFiles - namedFiles) { foreach (var entry in chunk.Entries) { entry.NameHash = stream.ReadUInt64(); } } else // no namehash { foreach (var entry in chunk.Entries) { entry.NameHash = 0; } } } else { foreach (var entry in chunk.Entries) { entry.CEKey = new MD5Hash(stream); entry.NameHash = stream.ReadUInt64(); maxId = Math.Max(maxId, entry.FileDataId); } } Chunks.Add(chunk); } if (GlobalRoot == null) { CASContainer.Logger.LogCritical($"No Global root found. Root file is corrupt."); return; } // use listfile to assign names var listFileLines = File.ReadAllLines(cdnPath); foreach (var listFileData in listFileLines) { var splitData = listFileData.Split(';'); if (splitData.Length != 2) { continue; } if (!uint.TryParse(splitData[0], out uint listFileDataID)) { continue; } ListFile[listFileDataID] = new Jenkins96().ComputeHash(splitData[1]); } foreach (var chunk in Chunks) { foreach (var entry in chunk.Entries) { if (entry.NameHash == 0) { if (ListFile.ContainsKey(entry.FileDataId)) { entry.NameHash = ListFile[entry.FileDataId]; } } } } // set maxid from cache maxId = Math.Max(Math.Max(maxId, minimumid), CASContainer.Settings.Cache?.MaxId ?? 0); // store encoding map encodingMap = (data as BLTEStream)?.EncodingMap.FirstOrDefault() ?? new EncodingMap(EncodingType.ZLib, 9); stream?.Dispose(); data?.Dispose(); }
protected SRFile(string path, Stream stream) : base(stream) { Path = path; RootChunk = new RootChunk(this); }