Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Data.SqlClient;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- namespace rdbStructure
- {
- /// <summary>
- /// To use a structure.dll with rEDIT follow these very simple rules:
- /// All structure fields must be defined as the proper type (e.g. Int32, Double, Single)
- /// All structure fields must be in the correct order (as they are written in the .rdb)
- /// The db_string rdb dynamically sets Length Handles, but other rdbs have set lengths, for those set primaryLengthOverride below
- /// </summary>
- public class structure
- {
- /// <summary>
- /// The structure defines the column list of the rdb
- /// </summary>
- /// specialField = field to read but not store for viewing in the datatable
- /// specialField: Length = field used to read a string (db_string) || make sure length fields contain the word "Length"
- /// specialField: Blank = field used to advance the reader by a given number of bytes (e.g. blank_LENGTHINBYTES)
- /// WARNING!!!! the fields must be arranged as the rdb or the read will fail!
- //////////////////////////////////////////
- //////////////////////////////////////////
- ///////////// Structure /////////////////
- //////////////////////////////////////////
- public Int32 job_id { get; set; }
- public Int32 skill_id { get; set; }
- public Int32 min_skill_lv { get; set; }
- public Int32 max_skill_lv { get; set; }
- public Int32 lv { get; set; }
- public Int32 job_lv { get; set; }
- public Single jp_ratio { get; set; }
- public Int32 need_skill_id_1 { get; set; }
- public Int32 need_skill_id_2 { get; set; }
- public Int32 need_skill_id_3 { get; set; }
- public Int32 need_skill_lv_1 { get; set; }
- public Int32 need_skill_lv_2 { get; set; }
- public Int32 need_skill_lv_3 { get; set; }
- //////////////////////////////////////////
- //////////////////////////////////////////
- ///////////////////////////////////////////////////
- /// <summary>
- /// primaryLengthOverride is used for db_tenacity,
- /// db_item and other rdb with static length strings
- /// WARNING!!!
- /// This value must be 0 if loading db_string!
- /// </summary>
- ///////////////////////////////////////////////////
- static int primaryLengthOverride = 0;
- static int secondaryLengthOverride = 0;
- ///////////////////////////////////////////////////
- ///////////////////////////////////////////
- /// <summary>
- /// In order to use "fromDB you will need to provide
- /// some information
- /// </summary>
- /// <param name="tableName">table to be selected @ database (MANDATORY)</param> Example: db_item.rdb <> dbo.ItemResource
- /// <param name="sortOn">the column the results will be sorted by (OPTIONAL)</param>
- /// <param name="sortDirection">ASC = Ascending, DESC = Descending</param>
- public static string tableName = "dbo.SkillTreeResource";
- public static string sortOn = null;
- public static string sortDirection = null;
- //////////////////////////////////////////
- //Columns to not add to the DataTable
- //Seperate words by , e.g. "your,face"
- ///////////////////////////////////////
- public static string specialFields = "";
- ///////////////////////////////////////
- ///////////////////////////////////////
- /////////////////////////////////////////////////////////////
- //Setting this to true will cause the reader to
- //read the first field of a loop as jobTreeCount
- //then read normal structure until currentTree = jobTreeCount
- /////////////////////////////////////////////////////////////
- public static bool isSkillTree = true;
- #region Structure Handles [DO NOT EDIT]
- #region Length Handles
- /// <summary>Lengths for relevant strings</summary>
- /// <param name="length1" >Used in reading strings</param>
- /// <param name="length2">Only used by db_string</param>
- static int primaryLength = 0;
- static int secondaryLength = 0;
- static int lengthCount = 0;
- static int stringCount = 0;
- #endregion
- #region Binary Reader/Write
- static BinaryReader reader = null;
- static BinaryWriter writer = null;
- #endregion
- #region File Header Info
- /// <summary>
- /// The fields below store data read from the header
- /// </summary>
- static string fileDate = null;
- static int fileRows = 0;
- #endregion
- #region DLL Handles
- static Type type = typeof(structure);
- static PropertyInfo[] properties = typeof(structure).GetProperties();
- #endregion
- #endregion
- #region rdb Processing (load/save) [DO NOT EDIT]
- /// <summary>
- /// Filters out specialFields (fields that are to be read, but not viewed)
- /// </summary>
- /// <param name="columnName">Column to be checked for (isSpecial)</param>
- /// <returns>True if a special field is detected / False elsewise</returns>
- /// WARNING!!!
- /// Do not edit below unless you are absolutely sure you know what you're doing!
- ////////////////////////////////////////////////////////////////////////////////
- public static bool isSpecial(string columnName)
- {
- string[] fieldCollection = specialFields.Split(',');
- bool blockDetected = false;
- for (int currentColumn = 0; currentColumn < fieldCollection.Length; currentColumn++)
- {
- if (!blockDetected)
- blockDetected = fieldCollection.Contains(columnName);
- }
- return blockDetected;
- }
- /// <summary>
- /// Checks for blankSpace fields (e.g. blank_16 will move the reader forward 16 bytes
- /// </summary>
- /// <param name="columnName">Column to be checked for blankSpace</param>
- /// <returns>True if column is a blank / False if columns is not a blank</returns>
- /// WARNING!!!
- /// Do not edit below unless you are absolutely sure you know what you're doing!
- ////////////////////////////////////////////////////////////////////////////////
- public static bool isBlank(string columnName)
- {
- if (columnName.ToLower().Contains("blank"))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// Parses the above structure into DataTable columns, that are then added to the outbound DataTable before
- /// data is read.
- /// INFO:
- /// To disallow special fields such as string lengths that need to be read but not viewed add them to specialFields
- /// with a , delimiter e.g. "your,face"
- /// </summary>
- /// <returns>A DataTable populated with columns</returns>
- /// WARNING!!!
- /// Do not edit below unless you are absolutely sure you know what you're doing!
- ////////////////////////////////////////////////////////////////////////////////
- public static DataTable prepareTable()
- {
- //Create an outbound DataTable to hold the rdb contents
- DataTable outTable = new DataTable();
- //create the columns for each property setting the name & type (generic)
- foreach (PropertyInfo property in properties)
- {
- bool special = isSpecial(property.Name);
- if (!special)
- {
- outTable.Columns.Add(property.Name, property.PropertyType);
- }
- }
- return outTable;
- }
- /// <summary>
- /// readFile reads a .rdb file into a DataTable
- /// </summary>
- /// <param name="rdbPath">Path of the rdb to read</param>
- /// <returns>Either populated datatable or null (error)</returns>
- /// WARNING!!!
- /// Do not edit below unless you are absolutely sure you know what you're doing!
- ////////////////////////////////////////////////////////////////////////////////
- public static DataTable readFile(string rdbPath)
- {
- //Create an outbound DataTable to store rdb data
- DataTable outTable = prepareTable();
- //Instantiate the BinaryReader
- reader = new BinaryReader(File.Open(rdbPath, FileMode.Open, FileAccess.Read));
- //If the reader is valid
- if (reader != null)
- {
- #region Read the RDB Header
- fileDate = Encoding.Default.GetString(reader.ReadBytes(8));
- reader.ReadBytes(120);
- fileRows = reader.ReadInt32();
- #endregion
- #region Read the RDB Contents
- DataRow newRow = null;
- /// <summary>
- /// Special rules below
- /// </summary>
- ////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////
- //Foreach each row in the rdb
- for (int curRow = 0; curRow < fileRows; curRow++) //Standard Loop
- {
- //If this is a skilltree rdb (a secondary loop must be used)
- if (isSkillTree)
- {
- //Read this rows jobTreeCount
- int jobTreeCount = reader.ReadInt32();
- //Foreach sub-row in the row
- for (int currentTree = 0; currentTree < jobTreeCount; currentTree++)
- {
- //Copy the columns from the outbound Table
- newRow = outTable.NewRow();
- //Populate the new row with Data from the RDB
- newRow = populateRow(newRow);
- //If the newRow is actually populated with data
- if (newRow != null)
- //Add the row to the outbound DataTable
- outTable.Rows.Add(newRow);
- }
- }
- else //This is not a skilltree rdb (no secondary loop needed)
- {
- //Copy the columns from the outbound Table
- newRow = outTable.NewRow();
- //Populate the new row with Data from the RDB
- newRow = populateRow(newRow);
- //If the newRow is actually populated with data
- if (newRow != null)
- //Add the row to the outbound DataTable
- outTable.Rows.Add(newRow);
- }
- }
- ////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////
- #endregion
- //Dispose the used reader
- reader.Dispose();
- //Return the prepared and populated DataTable
- return outTable;
- }
- else
- {
- return null;
- }
- }
- /// <summary>
- /// Populates a DataRow with relevant information
- /// </summary>
- /// <param name="newRow">DataRow formatted with columns</param>
- /// <returns>Formated DataRow populated with rdb data</returns>
- /// WARNING!!!
- /// Do not edit below unless you are absolutely sure you know what you're doing!
- ////////////////////////////////////////////////////////////////////////////////
- public static DataRow populateRow(DataRow newRow)
- {
- //Reset the length and string counts
- lengthCount = 0;
- stringCount = 0;
- /// <summary>Foreach Property in this structure
- /// read rdb based on Property.PropertyType</summary>
- /////////////////////////////////////////////////////
- /////////////////////////////////////////////////////
- foreach (PropertyInfo property in properties)
- {
- //If property isSpecial Length field
- if (property.Name.ToLower().Contains("length"))
- {
- //If the property is Int32 (almost all length fields are Int32)
- if (property.PropertyType == typeof(Int32))
- {
- //If this is the first Length being read
- if (lengthCount == 0)
- {
- primaryLength = reader.ReadInt32();
- }
- //If this is the second Length being read
- if (lengthCount == 1)
- {
- secondaryLength = reader.ReadInt32();
- }
- }
- //Increase amount of times Length has been counted
- lengthCount++;
- }
- else //This is not a length field
- {
- //Check if field has been marked isSpecial
- bool special = isSpecial(property.Name);
- //Check if field is marked as a Blank
- bool blank = isBlank(property.Name);
- //If field is blank space
- if (blank)
- {
- //split the blank and retrieve the bytes to advance
- string[] bytesToMove = property.Name.Split('_');
- //Advance the reader by bytesToMove
- reader.ReadBytes(Convert.ToInt32(bytesToMove[1]));
- }
- else
- {
- if (special)
- {
- if (property.PropertyType == typeof(Int16))
- {
- reader.ReadInt16();
- }
- if (property.PropertyType == typeof(Int32))
- {
- reader.ReadInt32();
- }
- }
- else
- {
- if (property.PropertyType == typeof(byte))
- {
- newRow[property.Name] = reader.ReadByte();
- }
- if (property.PropertyType == typeof(Int16))
- {
- newRow[property.Name] = reader.ReadInt16();
- }
- if (property.PropertyType == typeof(Int32))
- {
- newRow[property.Name] = reader.ReadInt32();
- }
- if (property.PropertyType == typeof(Int64))
- {
- newRow[property.Name] = reader.ReadInt64();
- }
- if (property.PropertyType == typeof(Single))
- {
- newRow[property.Name] = reader.ReadSingle();
- }
- if (property.PropertyType == typeof(Double))
- {
- newRow[property.Name] = reader.ReadDouble();
- }
- if (property.PropertyType == typeof(string))
- {
- //If string sized is static
- if (primaryLengthOverride != 0)
- {
- newRow[property.Name] = byteConverter.BytesToString(reader.ReadBytes(primaryLengthOverride));
- }
- else
- {
- if (stringCount == 0)
- {
- newRow[property.Name] = byteConverter.BytesToString(reader.ReadBytes(primaryLength));
- }
- if (stringCount == 1)
- {
- newRow[property.Name] = byteConverter.BytesToString(reader.ReadBytes(secondaryLength));
- }
- stringCount++;
- }
- }
- }
- }
- }
- }
- /////////////////////////////////////////////////////
- /////////////////////////////////////////////////////
- return newRow;
- }
- /// <summary>
- /// Creates a .rdb file from a designated DataTable
- /// </summary>
- /// <param name="rdbPath">Path of file to be created</param>
- /// <param name="inTable">DataTable to save the contents of</param>
- /// WARNING!!!
- /// Do not edit below unless you are absolutely sure you know what you're doing!
- ////////////////////////////////////////////////////////////////////////////////
- public static void saveFile(string rdbPath, DataTable inTable)
- {
- //Fetch table to save
- DataTable saveTable = inTable;
- //Create a BinaryWriter to read the file
- writer = new BinaryWriter(File.Create(rdbPath));
- //Define some length parameters
- //To be used for strings
- lengthCount = 0;
- primaryLength = 0;
- secondaryLength = 0;
- //If the table provided is valid
- if (saveTable != null)
- {
- //Fetch the amount of rows held within the table
- int rowCount = saveTable.Rows.Count;
- //Using our previously defined BinaryWriter
- using (writer)
- {
- //Write header
- writer.Write(byteConverter.GetFileHeader());
- //If this isn't a skilltree
- if (!isSkillTree)
- {
- //Write Row count
- writer.Write(rowCount);
- //Foreach row in the table
- foreach (DataRow row in saveTable.Rows)
- {
- //Write the row to file
- writeRow(row);
- }
- }
- else
- {
- int jobId = 0; //num3
- int previousJobId = 0; //num1
- int jobCount = 0; //num2
- List<int> wasRead = new List<int>();
- //Collect the jobSet count
- for (int i = 0; i < saveTable.Rows.Count; i++)
- {
- //Fetch current job_id
- jobId = (int)saveTable.Rows[i].Field<Int32>("job_id");
- //If jobId isn't equal to previousJobId
- if (previousJobId != jobId)
- {
- //Set previousJobId
- previousJobId = jobId;
- jobCount++; //jobTreeCount
- }
- }
- //Write the jobSet count
- writer.Write(jobCount);
- //Foreach row in saveTable
- for (int i = 0; i < saveTable.Rows.Count; i++)
- {
- //Get job_id for current row
- jobId = (int)saveTable.Rows[i].Field<Int32>("job_id");
- //Check if jobSet has already been read
- bool alreadyRead = wasRead.Contains(jobId);
- //If the current jobSet has not been read
- if (!alreadyRead)
- {
- //Collect the jobSet for this jobId
- DataRow[] jobTreeCollection = saveTable.Select(string.Format("job_id = {0}", jobId));
- //Count amount of jobTrees in the jobSet
- int jobTreeCount = jobTreeCollection.Count();
- //Write the jobTreeCount for this jobSet
- writer.Write(jobTreeCount);
- //Foreach jobTree inside the jobSet
- for (int currentJobTree = 0; currentJobTree < jobTreeCount; currentJobTree++)
- {
- //Write the row
- writeRow(jobTreeCollection[currentJobTree]);
- }
- //Mark the jobSet as read
- wasRead.Add(jobId);
- }
- }
- }
- }
- }
- }
- /// <summary>
- /// Writes a prepared DataRow to the .rdb
- /// </summary>
- /// <param name="currentRow">DataRow to be written</param>
- /// WARNING!!!
- /// Do not edit below unless you are absolutely sure you know what you're doing!
- ////////////////////////////////////////////////////////////////////////////////
- public static void writeRow(DataRow currentRow)
- {
- lengthCount = 0;
- //For each property in the structure
- foreach (PropertyInfo property in properties)
- {
- if (property.Name.ToLower().Contains("length"))
- {
- if (lengthCount == 0)
- {
- primaryLength = currentRow.Field<string>("name").Length + 1;
- writer.Write(primaryLength);
- }
- if (lengthCount == 1)
- {
- secondaryLength = currentRow.Field<string>("value").Length + 1;
- writer.Write(secondaryLength);
- }
- lengthCount++;
- }
- else
- {
- bool special = isSpecial(property.Name);
- bool blank = isBlank(property.Name);
- if (blank)
- {
- //split the blank and retrieve the bytes to advance
- string[] bytesToMove = property.Name.Split('_');
- //Advance the reader by bytesToMove
- writer.Write(new Byte[Convert.ToInt32(bytesToMove[1])]);
- }
- else
- {
- if (special)
- {
- if (property.PropertyType == typeof(Int16))
- {
- Int16 columnValue = currentRow.Field<Int16>(property.Name);
- writer.Write(columnValue);
- }
- if (property.PropertyType == typeof(Int32))
- {
- Int32 columnValue = currentRow.Field<Int32>(property.Name);
- writer.Write(columnValue);
- }
- }
- else
- {
- if (property.PropertyType == typeof(byte))
- {
- byte columnValue = currentRow.Field<byte>(property.Name);
- writer.Write(columnValue);
- }
- if (property.PropertyType == typeof(Int16))
- {
- Int16 columnValue = currentRow.Field<Int16>(property.Name);
- writer.Write(columnValue);
- }
- if (property.PropertyType == typeof(Int32))
- {
- Int32 columnValue = currentRow.Field<Int32>(property.Name);
- writer.Write(columnValue);
- }
- if (property.PropertyType == typeof(Int64))
- {
- Int64 columnValue = currentRow.Field<Int64>(property.Name);
- writer.Write(columnValue);
- }
- if (property.PropertyType == typeof(Single))
- {
- Single columnValue = currentRow.Field<Single>(property.Name);
- writer.Write(columnValue);
- }
- if (property.PropertyType == typeof(Double))
- {
- Double columnValue = currentRow.Field<Double>(property.Name);
- writer.Write(columnValue);
- }
- if (property.PropertyType == typeof(string))
- {
- string columnValue = currentRow.Field<string>(property.Name);
- writer.Write(byteConverter.StringToBytes(columnValue));
- if (primaryLengthOverride != 0)
- {
- writer.Write(new Byte[primaryLengthOverride - columnValue.Length]);
- }
- else
- {
- writer.Write(new Byte[1]);
- }
- }
- }
- }
- }
- }
- }
- #endregion
- #region db Processing (load) [DO NOT EDIT]
- /// <summary>
- /// Reads a relevant database table into a DataTable
- /// </summary>
- /// <param name="connectionString">Sql Connection string used to connect to the Database</param>
- /// <returns>A populated datatable</returns>
- /// WARNING!!!
- /// Do not edit below unless you are absolutely sure you know what you're doing!
- public static DataTable readDB(string connectionString)
- {
- DataTable outTable = new DataTable();
- string connString = connectionString;
- string query = generateSelect();
- SqlConnection conn = new SqlConnection(connString);
- SqlCommand cmd = new SqlCommand(query, conn);
- conn.Open();
- // create data adapter
- SqlDataAdapter da = new SqlDataAdapter(cmd);
- // this will query your database and return the result to your datatable
- da.Fill(outTable);
- conn.Close();
- da.Dispose();
- return outTable;
- }
- /// <summary>
- /// Generates a select statement based on this structures properties
- /// for use by readDB above
- /// </summary>
- /// <returns>A populated select statement</returns>
- /// WARNING!!!
- /// Do not edit below unless you are absolutely sure you know what you're doing!
- public static String generateSelect()
- {
- String selectStatement = "SELECT ";
- int propertyCount = 0;
- bool isLastProperty = false;
- int currentProperty = 0;
- foreach (PropertyInfo property in properties)
- {
- bool special = isSpecial(property.Name);
- if (!special)
- {
- propertyCount++;
- }
- }
- foreach (PropertyInfo property in properties)
- {
- string columnName = null;
- bool special = isSpecial(property.Name);
- if (!special)
- {
- currentProperty++;
- isLastProperty = currentProperty == propertyCount;
- if (!isLastProperty)
- {
- columnName = string.Concat(property.Name, ",");
- }
- else
- {
- columnName = property.Name;
- }
- selectStatement += string.Format("{0} ", columnName);
- }
- }
- string returnString = null;
- if (sortOn != null)
- {
- returnString = string.Format("{0} FROM {1} ORDER BY {2} {3}", selectStatement, tableName, sortOn, sortDirection);
- }
- else
- {
- returnString = string.Format("{0} FROM {1}", selectStatement, tableName);
- }
- return returnString;
- }
- #endregion
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement