예제 #1
0
        /// <summary>
        /// Uses polymorphic features of the IDataType interface to save the different data types differently
        /// Headers for all types of files match, save for the first 3 bytes, which use the file extension to
        ///		save the proper string.
        /// </summary>
        /// <param name="pubVersion">Version of the pub file to save. For Ethan's client, items should be 1, otherwise, this should be 0 (for now)</param>
        /// <param name="error">ref parameter that provides the Exception.Message string on an error condition</param>
        /// <returns>True if successful, false on failure. Use the 'error' parameter to check error message</returns>
        public bool Save(int pubVersion, ref string error)
        {
            try
            {
                using (FileStream sw = File.Create(FilePath))                 //throw exceptions on error
                {
                    if (FilePath.Length <= 4 || !FilePath.Contains('.'))
                    {
                        throw new ArgumentException("The filename of the data file must have a 3 letter extension. Use EIF, ENF, ESF, or ECF.");
                    }

                    //get the extension to write as the first 3 bytes
                    byte[] extension = Encoding.ASCII.GetBytes(FilePath.ToUpper().Substring(FilePath.LastIndexOf('.') + 1));
                    if (extension.Length != 3)
                    {
                        throw new ArgumentException("The filename of the data file must have a 3 letter extension. Use EIF, ENF, ESF, or ECF.");
                    }

                    //allocate the data array for all the data to be saved
                    byte[] allData;
                    //write the file to memory first
                    using (MemoryStream mem = new MemoryStream())
                    {
                        mem.Write(extension, 0, 3);                          //E[I|N|S|C]F at beginning
                        mem.Write(Packet.EncodeNumber(Rid, 4), 0, 4);        //rid
                        mem.Write(Packet.EncodeNumber(Data.Count, 2), 0, 2); //len

                        Version = pubVersion;
                        mem.WriteByte(Packet.EncodeNumber(Version, 1)[0]);                         //new version check

                        for (int i = 1; i < Data.Count; ++i)
                        {
                            byte[] toWrite = Data[i].SerializeToByteArray();
                            mem.Write(toWrite, 0, toWrite.Length);
                        }
                        allData = mem.ToArray();                         //get all data bytes
                    }

                    //write the data to the stream and overwrite whatever the rid is with the CRC
                    CRC32 crc    = new CRC32();
                    uint  newRid = crc.Check(allData, 7, (uint)allData.Length - 7);
                    Rid = (int)newRid;
                    sw.Write(allData, 0, allData.Length);
                    sw.Seek(3, SeekOrigin.Begin);                     //skip first 3 bytes
                    sw.Write(Packet.EncodeNumber(Rid, 4), 0, 4);      //overwrite the 4 RID (revision ID) bytes
                }
            }
            catch (Exception ex)
            {
                error = ex.Message;
                return(false);
            }

            error = "none";
            return(true);
        }
예제 #2
0
        public bool Save(string filename, bool saveAs = false)
        {
            if (isSaved && !saveAs)
            {
                return(true);
            }

            // Initially, write to a memory stream so we can CRC the data
            uint crcVal = 0;

            byte[] allBytes = null;
            using (MemoryStream ms = new MemoryStream())
            {
                ms.WriteInt(Const.MAGIC_NUMBER);

                // Map info
                ms.WriteInt((int)MapField.MapInfo);
                ms.WriteInt(w);
                ms.WriteInt(h);
                ms.WriteInt((int)Type);
                ms.WriteString(MapName);
                ms.WriteInt(Warp);
                ms.WriteInt(PlayerSpawn.X);
                ms.WriteInt(PlayerSpawn.Y);
                ms.WriteInt(layers.Length);

                // Write map layers
                foreach (SortedList <string, Tile> layer in this.layers)
                {
                    ms.WriteInt((int)MapField.MapLayer);

                    // Write number of tiles
                    ms.WriteInt(layer.Count);

                    foreach (Tile t in layer.Values)
                    {
                        if (t is AnimatedTile)
                        {
                            AnimatedTile at = (AnimatedTile)t;

                            ms.WriteInt((int)TileType.Animated);
                            ms.WriteInt(at.X);
                            ms.WriteInt(at.Y);
                            ms.WriteInt(at.Graphic);
                        }
                        else if (t is GraphicTile)
                        {
                            GraphicTile gt = (GraphicTile)t;

                            ms.WriteInt((int)TileType.Graphic);
                            ms.WriteInt(gt.X);
                            ms.WriteInt(gt.Y);
                            ms.WriteInt(gt.Graphic);
                        }
                        else if (t is SpecialTile)
                        {
                            SpecialTile st = (SpecialTile)t;

                            ms.WriteInt((int)TileType.Special);
                            ms.WriteInt(st.X);
                            ms.WriteInt(st.Y);
                            ms.WriteInt((int)st.Type);

                            switch (st.Type)
                            {
                            case SpecialTileSpec.CAVE:
                            case SpecialTileSpec.GRASS:
                            case SpecialTileSpec.WATER:
                                ms.WriteInt((int)st.SpawnID);
                                break;

                            case SpecialTileSpec.WARP:
                                ms.WriteInt(st.WarpMap);
                                ms.WriteInt(st.WarpX);
                                ms.WriteInt(st.WarpY);
                                ms.WriteInt((int)st.WarpAnim);
                                break;
                            }
                        }
                    }
                }

                // Write spawns
                int numSpawnsWritten = 0;
                foreach (Spawn sp in Spawns)
                {
                    // If this happens, we shouldn't write any more. Might as well stop now.
                    if (numSpawnsWritten > this.Spawns.Count)
                    {
                        break;
                    }

                    ms.WriteInt((int)MapField.SpawnInfo);
                    ms.WriteInt(sp.SpawnID);
                    ms.WriteString(sp.Name);
                    ms.WriteInt(sp.Spawns.Count);

                    int numPairsWritten = 0;
                    foreach (KeyValuePair <int, int> pair in sp.Spawns)
                    {
                        // Same error condition as before
                        if (numPairsWritten > sp.Spawns.Count)
                        {
                            break;
                        }

                        ms.WriteInt(pair.Key);
                        ms.WriteInt(pair.Value);

                        numPairsWritten++;
                    }

                    numSpawnsWritten++;
                }

                allBytes = new byte[ms.Length];
                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(allBytes, 0, allBytes.Length);
                CRC32 crc = new CRC32();
                crcVal = crc.Check(allBytes);
            }

            using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(filename)))
            {
                bw.Write(allBytes);
                bw.Write(ByteConverter.ToBytes(crcVal));
            }

            isSaved  = true;
            fileName = filename;

            return(isSaved);
        }
예제 #3
0
        /// <summary>
        /// Uses polymorphic features of the IDataType interface to save the different data types differently
        /// Headers for all types of files match, save for the first 3 bytes, which use the file extension to
        ///		save the proper string.
        /// </summary>
        /// <param name="pubVersion">Version of the pub file to save. For Ethan's client, items should be 1, otherwise, this should be 0 (for now)</param>
        /// <param name="error">ref parameter that provides the Exception.Message string on an error condition</param>
        /// <returns>True if successful, false on failure. Use the 'error' parameter to check error message</returns>
        public bool Save(int pubVersion, ref string error)
        {
            try
            {
                using (FileStream sw = File.Create(FilePath))                 //throw exceptions on error
                {
                    if (FilePath.Length <= 4 || !FilePath.Contains('.'))
                    {
                        throw new ArgumentException("The filename of the data file must have a 3 letter extension. Use EIF, ENF, ESF, or ECF.");
                    }

                    //get the extension to write as the first 3 bytes
                    byte[] extension = Encoding.ASCII.GetBytes(FilePath.ToUpper().Substring(FilePath.LastIndexOf('.') + 1));
                    if (extension.Length != 3)
                    {
                        throw new ArgumentException("The filename of the data file must have a 3 letter extension. Use EIF, ENF, ESF, or ECF.");
                    }

                    //allocate the data array for all the data to be saved
                    //this is done based on the type of the Data items
                    byte[] allData;
                    if (Data.Count > 0)
                    {
                        if (Data[0] is ItemRecord)
                        {
                            allData = new byte[10 + ItemFile.DATA_SIZE * Data.Count];
                        }
                        else if (Data[0] is NPCRecord)
                        {
                            allData = new byte[10 + NPCFile.DATA_SIZE * Data.Count];
                        }
                        else if (Data[0] is SpellRecord)
                        {
                            allData = new byte[10 + SpellFile.DATA_SIZE * Data.Count];
                        }
                        else if (Data[0] is ClassRecord)
                        {
                            allData = new byte[10 + ClassFile.DATA_SIZE * Data.Count];
                        }
                        else
                        {
                            throw new ArgumentException("The internal data container has records of invalid type. Memory is corrupted.");
                        }
                    }
                    else
                    {
                        throw new IndexOutOfRangeException("There are no data items to save!");
                    }

                    //write the file to memory first (wrapper around allData byte array)
                    using (MemoryStream mem = new MemoryStream(allData))
                    {
                        mem.Write(extension, 0, 3);                          //E[I|N|S|C]F at beginning
                        mem.Write(Packet.EncodeNumber(Rid, 4), 0, 4);        //rid
                        mem.Write(Packet.EncodeNumber(Data.Count, 2), 0, 2); //len

                        Version = pubVersion;
                        mem.WriteByte(Packet.EncodeNumber(Version, 1)[0]);                         //new version check

                        for (int i = 1; i < Data.Count; ++i)
                        {
                            byte[] toWrite = Data[i].SerializeToByteArray();
                            mem.Write(toWrite, 0, toWrite.Length);
                        }
                    }

                    //write the data to the stream and overwrite whatever the rid is with the CRC
                    CRC32 crc    = new CRC32();
                    uint  newRid = crc.Check(allData, 7, (uint)allData.Length - 7);
                    Rid = (int)newRid;
                    sw.Write(allData, 0, allData.Length);
                    sw.Seek(4, SeekOrigin.Begin);
                    sw.Write(Packet.EncodeNumber(Rid, 4), 0, 4);
                }
            }
            catch (Exception ex)
            {
                error = ex.Message;
                return(false);
            }

            error = "none";
            return(true);
        }
예제 #4
0
        public bool LoadFromStream(Stream s)
        {
            isLoaded = false;

            byte[] all;
            using (var memoryStream = new MemoryStream())
            {
                s.CopyTo(memoryStream);
                all = memoryStream.ToArray();
            }

            CRC32 crc    = new CRC32();
            uint  crcVal = crc.Check(all, 0, (uint)all.Length - 4); //crc everything except the value of the crc

            s.Seek(-sizeof(int), SeekOrigin.End);                   //last four bytes (int) is CRC value
            uint fileVal = (uint)s.ReadInt();

            if (crcVal != fileVal)
            {
                return(isLoaded);
            }

            s.Seek(0, SeekOrigin.Begin);

            if (s.ReadInt() != Const.MAGIC_NUMBER)
            {
                return(isLoaded);
            }

            spawns = new List <Spawn>();

            int loadedLayers = 0;

            while (s.Position < s.Length - 4)
            {
                switch ((MapField)s.ReadInt())
                {
                case MapField.MapInfo:
                    w           = s.ReadInt();
                    h           = s.ReadInt();
                    Type        = (MapType)s.ReadInt();
                    mapname     = s.ReadString();
                    Warp        = s.ReadInt();
                    PlayerSpawn = new Microsoft.Xna.Framework.Point(s.ReadInt(), s.ReadInt());
                    int numLayers = s.ReadInt();

                    if (numLayers != this.layers.Length)
                    {
                        throw new Exception("Invalid number of layers!");
                    }
                    break;

                case MapField.MapLayer:
                    int numTiles = s.ReadInt();
                    var newLayer = layers[loadedLayers] = new SortedList <string, Tile>(numTiles);

                    for (int i = 0; i < numTiles; i++)
                    {
                        Tile   toAdd = null;
                        LAYERS layer = LAYERS.Graphic;

                        switch ((TileType)s.ReadInt())
                        {
                        case TileType.Animated:
                            toAdd = new AnimatedTile(s.ReadInt(), s.ReadInt(), s.ReadInt());
                            layer = LAYERS.Graphic;
                            break;

                        case TileType.Graphic:
                            toAdd = new GraphicTile(s.ReadInt(), s.ReadInt(), s.ReadInt());
                            break;

                        case TileType.Special:
                            SpecialTile st = new SpecialTile(s.ReadInt(), s.ReadInt());

                            SpecialTileSpec tt    = (SpecialTileSpec)s.ReadInt();
                            object[]        param = null;
                            switch (tt)
                            {
                            case SpecialTileSpec.CAVE:
                            case SpecialTileSpec.GRASS:
                            case SpecialTileSpec.WATER:
                                param = new object[] { s.ReadInt() };
                                break;

                            case SpecialTileSpec.WARP:
                                param = new object[] { s.ReadInt(), s.ReadInt(), s.ReadInt(), (WarpAnim)s.ReadInt() };
                                break;
                            }

                            st.SetType(tt, param);
                            break;
                        }

                        if (toAdd != null)
                        {
                            AddTile(toAdd.X, toAdd.Y, layer, toAdd);
                        }
                    }

                    layers[loadedLayers++] = newLayer;
                    break;

                case MapField.SpawnInfo:
                    Spawn sp = new Spawn(s.ReadInt(), s.ReadString());

                    int numPairs = s.ReadInt();
                    for (int i = 0; i < numPairs; i++)
                    {
                        sp.AddSpawnPair(s.ReadInt(), s.ReadInt());
                    }
                    break;
                }
            }

            // Make sure we don't have any null layers (they cause problems later)
            for (int i = 0; i < layers.Length; i++)
            {
                if (layers[i] == null)
                {
                    layers[i] = new SortedList <string, Tile>();
                }
            }

            fileName = "";
            isLoaded = true;
            isSaved  = true;

            return(isLoaded);
        }
예제 #5
0
		///  <summary>
		///  Uses polymorphic features of the IDataType interface to save the different data types differently
		///  Headers for all types of files match, save for the first 3 bytes, which use the file extension to
		/// 		save the proper string.
		///  </summary>
		/// <param name="pubVersion">Version of the pub file to save. For Ethan's client, items should be 1, otherwise, this should be 0 (for now)</param>
		/// <param name="error">ref parameter that provides the Exception.Message string on an error condition</param>
		/// <returns>True if successful, false on failure. Use the 'error' parameter to check error message</returns>
		public bool Save(int pubVersion, out string error)
		{
			try
			{
				using (FileStream sw = File.Create(FilePath)) //throw exceptions on error
				{
					if (FilePath.Length <= 4 || !FilePath.Contains('.'))
						throw new ArgumentException("The filename of the data file must have a 3 letter extension. Use EIF, ENF, ESF, or ECF.");

					//get the extension to write as the first 3 bytes
					byte[] extension = Encoding.ASCII.GetBytes(FilePath.ToUpper().Substring(FilePath.LastIndexOf('.') + 1));
					if (extension.Length != 3)
						throw new ArgumentException("The filename of the data file must have a 3 letter extension. Use EIF, ENF, ESF, or ECF.");

					//allocate the data array for all the data to be saved
					byte[] allData;
					//write the file to memory first
					using (MemoryStream mem = new MemoryStream())
					{
						mem.Write(extension, 0, 3); //E[I|N|S|C]F at beginning
						mem.Write(Packet.EncodeNumber(Rid, 4), 0, 4); //rid
						mem.Write(Packet.EncodeNumber(Data.Count, 2), 0, 2); //len

						Version = pubVersion;
						mem.WriteByte(Packet.EncodeNumber(Version, 1)[0]); //new version check

						for (int i = 1; i < Data.Count; ++i)
						{
							byte[] toWrite = Data[i].SerializeToByteArray();
							mem.Write(toWrite, 0, toWrite.Length);
						}
						allData = mem.ToArray(); //get all data bytes
					}

					//write the data to the stream and overwrite whatever the rid is with the CRC
					CRC32 crc = new CRC32();
					uint newRid = crc.Check(allData, 7, (uint)allData.Length - 7);
					Rid = (int)newRid;
					sw.Write(allData, 0, allData.Length);
					sw.Seek(3, SeekOrigin.Begin); //skip first 3 bytes
					sw.Write(Packet.EncodeNumber(Rid, 4), 0, 4); //overwrite the 4 RID (revision ID) bytes
				}
			}
			catch (Exception ex)
			{
				error = ex.Message;
				return false;
			}

			error = "none";
			return true;
		}