public void StatRoom(CharacterData ch, int vnum) { // Attempt to find the room Models.RoomIndexData targetRoom = Program.World.Rooms.SingleOrDefault(r => r.VNUM.Equals(vnum)); // Did we find it? if (targetRoom == null) { // Inform the user Network.Send("No such location\n\r\n\r", ch.Descriptor); } else { string output = String.Empty; output += String.Format("Name: '{0}'\n\rArea: '{1}'\n\r", targetRoom.Name, Program.World.Areas.Single(a => a.MinVNum <= targetRoom.VNUM && a.MaxVNum >= targetRoom.VNUM).Name); output += String.Format("VNUM: {0} Sector: {1} Light: {2} Healing: {3} Mana: {4}\n\r", targetRoom.VNUM, targetRoom.SectorType.ToString(), targetRoom.LightLevel, targetRoom.HealRate.ToString(), targetRoom.ManaRate.ToString()); output += String.Format("Room Flags: {0}\n\r", ((Enums.AlphaMacros)targetRoom.Attributes).ToString().Replace(",", "").Replace(" ", "")); output += String.Format("Description:\n\r{0}\n\r", targetRoom.Description); output += "Extra description keywords: " + String.Join(",", targetRoom.ExtraDescriptions.Select(ed => ed.Keywords)) + "\n\r"; // TODO: Should check that the character can be seen by the person invoking this command output += "Characters: " + String.Join(",", targetRoom.Characters.Select(person => person.Name)) + "\n\r"; output += "Objects: " + String.Join(",", targetRoom.Objects.Select(obj => obj.Name)) + "\n\r"; // Loop over possible exits for (int i = 0; i <= 5; i++) { // Check that the exit is defined if (targetRoom.Exits[i] != null) { // Add to output output += String.Format("Door: {0}. To: {1}. Key: {2}. Exit flags: {3}.\n\rKeyword: '{4}'. Description: {5}\n\r", i, targetRoom.Exits[i].ToVNUM, targetRoom.Exits[i].KeyVNUM, ((Enums.AlphaMacros)targetRoom.Exits[i].Attributes).ToString(), targetRoom.Exits[i].Keywords, targetRoom.Exits[i].Description); } } output += "\n\r"; // Send output to the user Network.Send(output, ch.Descriptor); } }
/// <summary> /// Parses room flags and sector type definition for a room /// </summary> /// <returns><c>true</c>, if room flags and sector type were parsed, <c>false</c> otherwise.</returns> /// <param name="outRoom">Room to set the flags in</param> /// <param name="lineData">Line data to parse</param> /// <param name="lineNum">Current line number, used for error messages</param> /// <param name="areaFile">Filename of the area being parsed, used for error messages.</param> private static bool ParseRoomFlagsAndSectorType(RoomIndexData outRoom, string lineData, int lineNum, string areaFile) { // Split the line on space string[] splitLine = lineData.Split(' '); // Should be three parts; throw an error if not if (splitLine.Length != 3) { // Log an error and return null Logging.Log.Error(String.Format("Error parsing room flags & sector type of room {0} in area {1} on line {2}: expected three parts, encountered {3} in data {4}", outRoom.VNUM, areaFile, lineNum, splitLine.Length, lineData)); return(false); } // First part is obsolete - start with part 2, room flags // Convert the ROM flags to RoomAttributes outRoom.Attributes = AlphaConversions.ConvertROMAlphaToRoomAttributes(splitLine[1]); int sectType = 0; if (!Int32.TryParse(splitLine[2], out sectType)) { // Log an error and return null Logging.Log.Error(String.Format("Error parsing sector type of room {0} in area {1} on line {2}: could not convert value \"{3}\" to integer", outRoom.VNUM, areaFile, lineNum, splitLine[2])); return(false); } // Validate the value if (!Enum.IsDefined(typeof(SectorType), sectType)) { // Log an error and return null Logging.Log.Error(String.Format("Error parsing sector type of room {0} in area {1} on line {2}: invalid sector type {3}", outRoom.VNUM, areaFile, lineNum, sectType)); return(false); } // Store the sector type outRoom.SectorType = (SectorType)sectType; // All done return(true); }
private static Exit ParseExit(StringReader sr, RoomIndexData outRoom, string lineData, ref int lineNum, string areaFile) { // Instantiate a new ExitAttributes object to hold the exit data Exit exit = new Exit(); // The second character should be an integer int exitDirection = -1; if (!Int32.TryParse(lineData[1].ToString(), out exitDirection)) { Logging.Log.Error(String.Format("Error parsing exits of room {0} in area {1}: expected a numeric exit number on line {2} character 2 but instead found {3}", outRoom.VNUM, areaFile, lineNum, lineData[1])); return(null); } else { // Test that the exitNum is valid if (exitDirection > Enum.GetValues(typeof(Enums.Direction)).Length - 1) { Logging.Log.Error(String.Format("Error parsing exits of room {0} in area {1}: invalid exit direction {2} found on line {3}", outRoom.VNUM, areaFile, exitDirection, lineNum)); return(null); } else { // Valid exit direction, store it exit.Direction = (Enums.Direction)exitDirection; } } // Begin reading the exit description bool readingExitDescription = true; while (readingExitDescription) { // Read the next line lineData = sr.ReadLine(); lineNum++; // Is the line a sole tilde? If so, we're done. if (lineData.Equals("~")) { readingExitDescription = false; } else { // Append to the exit's description - trim any trailing tildes (stock Quifael does this) exit.Description += lineData.TrimEnd('~'); // If the line ends with ~, we're done reading if (lineData.EndsWith("~", StringComparison.CurrentCulture)) { readingExitDescription = false; } } } // Begin reading the exit keywords bool readingKeywords = true; while (readingKeywords) { // Pull the next line and store as the keywords lineData = sr.ReadLine(); lineNum++; if (lineData.Equals("~")) { readingKeywords = false; } else { // Append to the exit's keywords - trim any trailing tildes exit.Keywords += lineData.TrimEnd('~'); // If the line end with ~, we're done reading if (lineData.EndsWith("~", StringComparison.CurrentCulture)) { readingKeywords = false; } } } // Pull the final line of the exit definition, [lock #] [key #] [toRoom #] lineData = sr.ReadLine(); lineNum++; // Split the line on spaces string[] splitLine = lineData.Split(' '); // Expecting three segments if (splitLine.Length != 3) { Logging.Log.Error(String.Format("Error parsing exits of room {0} in area {1}: invalid lock-key-room line, expected 3 segments but got {2} - value {3} on line {4}", outRoom.VNUM, areaFile, splitLine.Length, lineData, lineNum)); return(null); } // First segment - value should be 0-2 according to the // ROM2.4b6 area.txt documentation, but the code accepts // values from 0-4, so we'll use those. Interestingly, // these map to the EX_* macros in merc.h, but at least for // rooms, there are some values (e.g. EX_HARD and // EX_INFURIATING) that go unused; perhaps object suse them? int door = 0; if (!Int32.TryParse(splitLine[0], out door)) { Logging.Log.Error(String.Format("Error parsing exits of room {0} in area {1}: door type is invalid, expected an integer but got {2} on line {3}", outRoom.VNUM, areaFile, splitLine[0], lineNum)); return(null); } if (door < 0 || door > 4) { Logging.Log.Error(String.Format("Error parsing exits of room {0} in area {1}: door type is invalid, expected value from 0-4, got {2} on line {3}", outRoom.VNUM, areaFile, splitLine[0], lineNum)); return(null); } switch (door) { case 0: // Not a door, do nothing break; case 1: // Is door. exit.Attributes = ExitAttributes.Door; break; case 2: // Pickproof door exit.Attributes = ExitAttributes.Door | ExitAttributes.PickProof; break; case 3: // Gandalf door exit.Attributes = ExitAttributes.Door | ExitAttributes.NoPass; break; case 4: // A door that's sort of not a door exit.Attributes = ExitAttributes.Door | ExitAttributes.NoPass | ExitAttributes.PickProof; break; } // Second segment - value should be positive integer, the VNUM of the key object int key = 0; if (!Int32.TryParse(splitLine[1], out key)) { Logging.Log.Error(String.Format("Error parsing exits of room {0} in area {1}: key VNUM is invalid, expected integer value but got {2} on line {3}", outRoom.VNUM, areaFile, splitLine[1], lineNum)); return(null); } // Key VNUM is -1 and up if (key < -1) { Logging.Log.Info(String.Format("Error parsing exits of room {0} in area {1}: key VNUM is invalid, must be greater than zero - got value {2} on line {3}", outRoom.VNUM, areaFile, splitLine[1], lineNum)); return(null); } // Set the exit's key's VNUM exit.KeyVNUM = key; // Third argument - value should be positive integer, the VNUM of the room the door leads to int exitRoomVNUM = 0; if (!Int32.TryParse(splitLine[2], out exitRoomVNUM)) { Logging.Log.Error(String.Format("Error parsing exits of room {0} in area {1}: exit room VNUM is invalid, expected integer value but got {2} on line {3}", outRoom.VNUM, areaFile, splitLine[2], lineNum)); return(null); } // Exit room VNUMs are zero or greater if (exitRoomVNUM < -1) { Logging.Log.Error(String.Format("Error parsing exits of room {0} in area {1}: exit room VNUM is invalid, must be greater than zero - got value {2} on line {3}", outRoom.VNUM, areaFile, exitRoomVNUM, lineNum)); return(null); } // Set the exit roomTo exit.ToVNUM = exitRoomVNUM; // Return the exit data return(exit); }
internal static RoomIndexData ParseRoomData(ref StringReader sr, string areaFile, ref int lineNum, string firstLine) { Logging.Log.Debug(String.Format("ParseRoomData() called for area {0} starting on line {1}", areaFile, lineNum)); // Instantiate variables for the method RoomIndexData outRoom = new RoomIndexData(); string lineData = firstLine; bool readingRooms = true; //// Read line //lineData = sr.ReadLine(); //lineNum++; // First, pull the vnum; then set it, if it's valid int vnum = Data.ParseVNUM(lineData); if (!vnum.Equals(0)) { outRoom.VNUM = vnum; // Rooms with VNUMs 3000-3399 are hard-coded to be law...ed? WTF is the right term for this? if (3000 <= outRoom.VNUM && outRoom.VNUM < 3400) { outRoom.Attributes |= RoomAttributes.Law; } } else { return(null); } Logging.Log.Debug(String.Format("Found room definition for vnum {0} beginning on line {1}", outRoom.VNUM, lineNum)); // Read the room name - one line, terminated with a tilde at the end outRoom.Name = sr.ReadLine().TrimEnd('~'); lineNum++; // Next, read the description outRoom.Description = Data.ReadLongText(sr, ref lineNum, areaFile, outRoom.VNUM); // Then, read the next line and parse as room flags and sector type lineData = sr.ReadLine(); lineNum++; ParseRoomFlagsAndSectorType(outRoom, lineData, lineNum, areaFile); // Finally, read remaining possible line definitions while (readingRooms) { // Read the next line lineData = sr.ReadLine(); lineNum++; //Logging.Log.Debug(String.Format("Reading line {0}, begins with {1}", lineNum, lineData[0])); // Flow control based on the first letter of the line if (lineData.Length > 0) // Temporary - once we handle everything, this shouldn't happen any more. { switch (lineData[0]) { case 'C': // TODO: Implement setting rooms as belonging to a clan break; case 'D': // Room exit Exit roomExit = ParseExit(sr, outRoom, lineData, ref lineNum, areaFile); // If the exit is not null, set it if (roomExit != null) { outRoom.Exits[(int)roomExit.Direction] = roomExit; } break; case 'E': // Room extra descriptions ExtraDescription desc = new ExtraDescription(); // Read the next line lineData = sr.ReadLine(); lineNum++; // Store the value as the description's keyowrds desc.Keywords = lineData.TrimEnd('~'); bool readingDescription = true; StringBuilder sb = new StringBuilder(); while (readingDescription) { // Read the line lineData = sr.ReadLine().Trim(); lineNum++; // Check that the line either is only a tilde, or ends with a tilde if (lineData.Trim().Equals("~") || (lineData.Length > 0 && lineData[lineData.Length - 1] == '~')) { readingDescription = false; } else { sb.AppendLine(lineData); } } // Store the description desc.Description = sb.ToString(); // Append the ExtraDescription to the room outRoom.ExtraDescriptions.Add(desc); break; case 'H': case 'M': int heal, mana; // Parse the line ParseHealManaRateDef(lineData, outRoom.VNUM, ref lineNum, areaFile, out heal, out mana); // Set the values outRoom.HealRate = heal; outRoom.ManaRate = mana; break; case 'O': // TODO: Implement room ownership break; case 'S': // We're finished reading the area readingRooms = false; Logging.Log.Debug(String.Format("Finished reading room {0} of area {1} on line {2}", outRoom.VNUM, areaFile, lineNum)); break; default: Logging.Log.Warn(String.Format("Encounted unexpected identifier {0} in room {1} of area {2} on line {3}", lineData[0], outRoom.VNUM, areaFile, lineNum)); break; } } } return(outRoom); }
public static AreaData LoadFromFile(string areaPath) { // Check that the file exists //try //{ int lineNum = 0; string lineData; string areaFile = Path.GetFileName(areaPath); AreaReadingState state = AreaReadingState.WaitingForSection; AreaData areaOut = new AreaData(); int errors = 0; int loaded = 0; bool backFromError = false; if (!File.Exists(areaPath)) { // Log an error and return null Logging.Log.Error(String.Format("Unable to load requested area file {0}", areaPath)); return(null); } // Instantiate a StreamReader and read the entire file StreamReader sr = new StreamReader(areaPath); string fileData = sr.ReadToEnd(); sr.Dispose(); // Instantiate a StreamReader for the file StringReader strRdr = new StringReader(fileData); // Parse the file, one line at a time. while ((lineData = strRdr.ReadLine()) != null) { // Increment lineNum lineNum++; switch (state) { case AreaReadingState.WaitingForSection: // Skip blank lines while in this state if (lineData.Trim().Equals(String.Empty)) { Logging.Log.Debug(String.Format("Skipping empty line at {0}:{1}", areaFile, lineNum)); continue; } // Expect the first data line we come across to start with # if (!lineData.StartsWith("#", StringComparison.InvariantCulture)) { // Log an error and return null Logging.Log.Error(String.Format("Error parsing {0} line {1}: Expected a section identifier, instead got {2}", areaFile, lineNum, lineData)); return(null); } // We've encountered a section heading; which one? switch (lineData.Trim().ToUpper()) { #region #$ // End-of-File Heading case "#$": // Log Logging.Log.Debug(String.Format("Found #$ EOF marker in file {0} on line {1}, finishing up", areaFile, lineNum)); // Set state to finished state = AreaReadingState.Finished; break; #endregion #region #OBJECTS case "#OBJECTS": Logging.Log.Debug(String.Format("Found #OBJECTS heading in file {0} on line {1}", areaFile, lineNum)); // Continue reading until we hit a #0 bool readingObjects = true; backFromError = false; errors = 0; loaded = 0; while (readingObjects) { // Read a line lineData = strRdr.ReadLine(); lineNum++; // If we've recently come back from failing to load a mob, we need to ignore some lines // until we get to the start of the next mob definition if (backFromError) { // If the line is not the section terminator but it does begin with #, it is // (should be) a new mob definition, so un-set the backFromError flag if (!lineData.Trim().Equals("#0") && lineData.Trim().Length > 0 && lineData.Trim()[0].Equals('#')) { // Un-set the backFromError flag; it's time to resume loading backFromError = false; Logging.Log.Debug(String.Format("Resuming loading of #OBJECTS section in area {0} on line {1} with mob {2}", areaFile, lineNum, lineData.Trim())); } // Otherwise, just move on to the next iteration of the loop else { continue; } } if (lineData == null) { readingObjects = false; } else if (lineData.Trim().Equals("#0")) { readingObjects = false; } else if (!lineData.Trim().Equals("#0") && !lineData.Trim().Equals("#$") && !lineData.Trim().Equals("")) { try { ObjectPrototypeData newObj = ObjectPrototypeData.ParseObjectData(ref strRdr, areaFile, ref lineNum, lineData); // If we have a loaded room, add it to the world if (newObj != null) { Program.World.Objects.Add(newObj); loaded++; } else { // Record a failed mob load, and set the indicator that we're back because of an error and should keep reading // but do nothing until we find a new mob errors++; backFromError = true; } } catch (ObjectParsingException ex) { Logging.Log.Error(String.Format("Error parsing object: {0}", ex.Message)); } } } Logging.Log.Debug(String.Format("Finished reading #OBJECTS section of file {0} on line {1} - loaded {2} objects, failed loading {3} mobs", areaFile, lineNum, loaded, errors)); break; #endregion #region #RESETS case "#RESETS": Logging.Log.Debug(String.Format("Found #RESETS heading in file {0} on line {1}", areaFile, lineNum)); // Continue reading until we hit a #0 bool readingResets = true; backFromError = false; errors = 0; loaded = 0; ResetData lastMob = null; while (readingResets) { // Read a line lineData = strRdr.ReadLine(); lineNum++; if (lineData == null) { readingResets = false; } else if (lineData.Trim().Equals("S")) { readingResets = false; } else if (!lineData.Trim().Equals("S") && !lineData.Trim().Equals("#$") && !lineData.Trim().Equals("")) { try { // Parse the reset ResetData newReset = ResetData.ParseResetData(areaFile, ref lineNum, lineData, lastMob); // Check that the reset parsed if (newReset != null) { // Special handling if the new reset is an E(quip) or G(ive) if (newReset.Command == ResetCommand.EquipObjectOnMob || newReset.Command == ResetCommand.GiveObjectToMob) { // Nest in the mob reset it relates to lastMob.Inner.Add(newReset); } else { // Otherwise, add the reset to the area areaOut.Resets.Add(newReset); } // If the reset was to spawn a M(ob), reset lastMob if (newReset.Command == ResetCommand.SpawnMobile) { lastMob = newReset; } // Finally, increment the loaded count loaded++; } else { // Record a failed mob load, and set the indicator that we're back because of an error and should keep reading // but do nothing until we find a new mob errors++; backFromError = true; } } catch (ObjectParsingException ex) { Logging.Log.Error(String.Format("Error parsing object: {0}", ex.Message)); } } } break; #endregion #region #SHOPS case "#SHOPS": Logging.Log.Debug(String.Format("Found #SHOPS heading in file {0} on line {1}", areaFile, lineNum)); // Continue reading until we hit a #0 bool readingShops = true; backFromError = false; errors = 0; loaded = 0; while (readingShops) { // Read a line lineData = strRdr.ReadLine(); lineNum++; // If we've recently come back from failing to load a mob, we need to ignore some lines // until we get to the start of the next mob definition if (backFromError) { // If the line is not the section terminator but it does begin with #, it is // (should be) a new mob definition, so un-set the backFromError flag if (!lineData.Trim().Equals("#0") && lineData.Trim().Length > 0 && lineData.Trim()[0].Equals('#')) { // Un-set the backFromError flag; it's time to resume loading backFromError = false; Logging.Log.Debug(String.Format("Resuming loading of #SHOPS section in area {0} on line {1} with mob {2}", areaFile, lineNum, lineData.Trim())); } // Otherwise, just move on to the next iteration of the loop else { continue; } } if (lineData == null) { readingShops = false; } else if (lineData.Trim().Equals("#0")) { readingShops = false; } else if (!lineData.Trim().Equals("#0") && !lineData.Trim().Equals("#$") && !lineData.Trim().Equals("")) { // TODO: Implement #SHOPS parsing } } break; #endregion #region #SPECIALS case "#SPECIALS": Logging.Log.Debug(String.Format("Found #SPECIALS heading in file {0} on line {1}", areaFile, lineNum)); // Continue reading until we hit a #0 bool readingSpecials = true; backFromError = false; errors = 0; loaded = 0; while (readingSpecials) { // Read a line lineData = strRdr.ReadLine(); lineNum++; // If we've recently come back from failing to load a mob, we need to ignore some lines // until we get to the start of the next mob definition if (backFromError) { // If the line is not the section terminator but it does begin with #, it is // (should be) a new mob definition, so un-set the backFromError flag if (!lineData.Trim().Equals("#0") && lineData.Trim().Length > 0 && lineData.Trim()[0].Equals('#')) { // Un-set the backFromError flag; it's time to resume loading backFromError = false; Logging.Log.Debug(String.Format("Resuming loading of #SPECIALS section in area {0} on line {1} with mob {2}", areaFile, lineNum, lineData.Trim())); } // Otherwise, just move on to the next iteration of the loop else { continue; } } if (lineData == null) { readingSpecials = false; } else if (lineData.Trim().Equals("#0")) { readingSpecials = false; } else if (!lineData.Trim().Equals("#0") && !lineData.Trim().Equals("#$") && !lineData.Trim().Equals("")) { // TODO: Implement #SPECIALS parsing } } break; #endregion #region #MOBILES case "#MOBILES": Logging.Log.Debug(String.Format("Found #MOBILES heading in file {0} on line {1}", areaFile, lineNum)); errors = 0; loaded = 0; backFromError = false; // Continue reading until we hit a #0 bool readingMobs = true; while (readingMobs) { // Read a line lineData = strRdr.ReadLine(); lineNum++; // If we've recently come back from failing to load a mob, we need to ignore some lines // until we get to the start of the next mob definition if (backFromError) { // If the line is not the section terminator but it does begin with #, it is // (should be) a new mob definition, so un-set the backFromError flag if (!lineData.Trim().Equals("#0") && lineData.Trim().Length > 0 && lineData.Trim()[0].Equals('#')) { // Un-set the backFromError flag; it's time to resume loading backFromError = false; Logging.Log.Debug(String.Format("Resuming loading of #MOBILES section in area {0} on line {1} with mob {2}", areaFile, lineNum, lineData.Trim())); } // Otherwise, just move on to the next iteration of the loop else { continue; } } if (lineData == null) { readingMobs = false; } else if (lineData.Trim().Equals("#0")) { readingMobs = false; } else if (!lineData.Trim().Equals("#0") && !lineData.Trim().Equals("#$") && !lineData.Trim().Equals("")) { MobPrototypeData newMob = MobPrototypeData.ParseMobData(ref strRdr, areaFile, ref lineNum, lineData); // If we have a loaded room, add it to the world if (newMob != null) { Program.World.Mobs.Add(newMob); loaded++; } else { // Record a failed mob load, and set the indicator that we're back because of an error and should keep reading // but do nothing until we find a new mob errors++; backFromError = true; } } } Logging.Log.Debug(String.Format("Finished reading #MOBILES section of file {0} on line {1} - loaded {2} mobs, failed loading {3} mobs", areaFile, lineNum, loaded, errors)); break; #endregion #region #ROOMS case "#ROOMS": Logging.Log.Debug(String.Format("Found #ROOMS heading in file {0} on line {1}", areaFile, lineNum)); // Continue reading until we hit a #0 bool readingRooms = true; backFromError = false; errors = 0; loaded = 0; while (readingRooms) { // Read a line lineData = strRdr.ReadLine(); lineNum++; // If we've recently come back from failing to load a mob, we need to ignore some lines // until we get to the start of the next mob definition if (backFromError) { // If the line is not the section terminator but it does begin with #, it is // (should be) a new mob definition, so un-set the backFromError flag if (!lineData.Trim().Equals("#0") && lineData.Trim().Length > 0 && lineData.Trim()[0].Equals('#')) { // Un-set the backFromError flag; it's time to resume loading backFromError = false; Logging.Log.Debug(String.Format("Resuming loading of #ROOMS section in area {0} on line {1} with mob {2}", areaFile, lineNum, lineData.Trim())); } // Otherwise, just move on to the next iteration of the loop else { continue; } } if (lineData == null) { readingRooms = false; } else if (lineData.Trim().Equals("#0")) { readingRooms = false; } else if (!lineData.Trim().Equals("#0") && !lineData.Trim().Equals("#$") && !lineData.Trim().Equals("")) { RoomIndexData newRoom = RoomIndexData.ParseRoomData(ref strRdr, areaFile, ref lineNum, lineData); // If we have a loaded room, add it to the world if (newRoom != null) { loaded++; Program.World.Rooms.Add(newRoom); } else { errors++; backFromError = true; } } } Logging.Log.Debug(String.Format("Finished reading #ROOMS section of file {0} on line {1} - loaded {2} rooms, failed loading {3} rooms", areaFile, lineNum, loaded, errors)); break; default: break; #endregion #region #AREA // AREA Heading case "#AREA": Logging.Log.Debug(String.Format("Found #AREA heading in file {0} on line {1}", areaFile, lineNum)); #region Filename // Read the next line - will be the area filename lineData = strRdr.ReadLine(); lineNum++; // Trim the trailing tilde lineData = lineData.Substring(0, lineData.Trim().Length - 1); // Set filename areaOut.Filename = lineData; Logging.Log.Debug(String.Format("Read area filename in file {0} on line {1}", areaFile, lineNum)); #endregion #region Name // Read the next line - will be the area name lineData = strRdr.ReadLine(); lineNum++; // Trim the trailing tilde lineData = lineData.Substring(0, lineData.Trim().Length - 1); // Set name areaOut.Name = lineData; Logging.Log.Debug(String.Format("Read area name in file {0} on line {1}", areaFile, lineNum)); #endregion #region Credits // Read the next line - will be the credits lineData = strRdr.ReadLine(); lineNum++; // Trim the trailing tilde lineData = lineData.Substring(0, lineData.Trim().Length - 1); // Set credits areaOut.Credits = lineData; Logging.Log.Debug(String.Format("Read credits information in file {0} on line {1}", areaFile, lineNum)); #endregion #region MinVNUM and MaxVNUM // Read the next line - will be the VNUM values lineData = strRdr.ReadLine(); lineNum++; // Split the line on space string[] vnumData = lineData.Trim().Split(' '); // Should be two values if (!vnumData.Length.Equals(2)) { // Log an error and return null Logging.Log.Error(String.Format("Error parsing {0} line {1}: Expected two numbers separated by space for VNUM limits, instead found {2}", areaFile, lineNum, lineData)); return(null); } // Tracks which of the two numbers we're on bool firstNum = true; // Loop over the two values, each should convert to an integer foreach (string vnum in vnumData) { int intVal; // Try to parse the value as a 32-bit integer if (!Int32.TryParse(vnum, out intVal)) { // Log an error and return null Logging.Log.Error(String.Format("Error parsing {0} line {1}: Error converting VNUM value {2} to an integer", areaFile, lineNum, vnum)); return(null); } else { if (firstNum) { areaOut.MinVNum = intVal; firstNum = false; } else { areaOut.MaxVNum = intVal; } } } Logging.Log.Debug(String.Format("Finished processing #AREA section of file {0} at line {1}", areaFile, lineNum)); #endregion break; #endregion } break; default: break; } } strRdr.Dispose(); // Return the output area return(areaOut); //} //catch (Exception e) //{ // // Log the exception and rethrow // Logging.Log.Fatal(String.Format("Unhandled exception caught: {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace)); // throw (e); //} }