/// <summary> /// Loads this map from a given object or file path. /// </summary> /// <param name="url">Url of file to open map from. </param> /// <param name="password">If a password is required to open this map, this will be used.</param> /// <param name="baseNode">The base node that all loading should be started from, this allows you to ignore this node and any nodes higher in the graph like the Root Camera.</param> /// <param name="keepPersistent">If set to true persistent ob jects will be kept.</param> /// <param name="keepCameras">If set to true all cameras will not be destroyed.</param> public void Load(object url, string password, SceneNode baseNode, bool keepPersistent, bool keepCameras) { // Keep track of the url. if (url is string) { _url = url as string; } // Try and open a stream to the file. Stream stream = StreamFactory.RequestStream(url, StreamMode.Open); if (stream == null) { return; } BinaryReader reader = new BinaryReader(stream); // Check the header of this file to make sure it really is a Fusion map file. if (reader.ReadChar() != 'F' || reader.ReadChar() != 'M' || reader.ReadChar() != 'P') { throw new Exception("Fusion map file has invalid header, file may be corrupt."); } // Read in the bit mask explaining the header. int headerBitMask = reader.ReadByte(); if ((headerBitMask & 4) != 0) { _mapProperties.Name = reader.ReadString(); } if ((headerBitMask & 8) != 0) { _mapProperties.Author = reader.ReadString(); } if ((headerBitMask & 16) != 0) { _mapProperties.Description = reader.ReadString(); } if ((headerBitMask & 32) != 0) { _mapProperties.Version = reader.ReadSingle(); } // Read in the rest of the file into memory so we can decompress / decrypt it. byte[] fileData = reader.ReadBytes((int)(stream.Length - stream.Position)); // Decrypt the data if required. if ((headerBitMask & 2) != 0) { fileData = DataMethods.Decrypt(fileData, password); } // Decompress the data if required. if ((headerBitMask & 1) != 0) { fileData = DataMethods.Inflate(fileData); } // Create a memory stream and a binary reader so we can minipulate the data better. MemoryStream memStream = new MemoryStream(fileData, 0, fileData.Length); BinaryReader memStreamReader = new BinaryReader(memStream); // Read in the encryption header to make sure everything went correctly. if ((headerBitMask & 2) != 0 || (headerBitMask & 1) != 0) { if (memStreamReader.ReadChar() != 'C' || memStreamReader.ReadChar() != 'H' || memStreamReader.ReadChar() != 'K') { throw new Exception("Unable to open Fusion map file, password is invalid or fils is corrupted."); } } // Read in the tileset pool used to render tilemap segments. int tilesetCount = memStreamReader.ReadByte(); Tileset.TilesetPool.Clear(); for (int i = 0; i < tilesetCount; i++) { if (memStreamReader.ReadBoolean() == true) { string newTilesetUrl = memStreamReader.ReadString(); if (newTilesetUrl.ToString().ToLower().StartsWith("pak@")) { newTilesetUrl = newTilesetUrl.ToString().Substring(4); // Legacy support. } if (Runtime.Resources.ResourceManager.ResourceIsCached(newTilesetUrl)) { Tileset.AddToTilesetPool(Runtime.Resources.ResourceManager.RetrieveResource(newTilesetUrl) as Tileset); } else { Runtime.Debug.DebugLogger.WriteLog("Loading tileset from " + newTilesetUrl); Tileset newTileset = new Tileset(); newTileset.Load(newTilesetUrl); Tileset.AddToTilesetPool(newTileset); Runtime.Resources.ResourceManager.CacheResource(newTilesetUrl, newTileset); } } } // Tell the scene graph to load itself from this memory stream. _sceneGraph.Load(memStreamReader, keepPersistent, keepCameras, baseNode); // Free up the memory stream and reader. memStream.Close(); memStream = null; // Free up the reader and stream. stream.Close(); stream = null; // Reclaim memory used during loading. GC.Collect(); }