Jump to content

Mythli

Members
  • Posts

    25
  • Joined

  • Last visited

    Never
  • Donations

    0.00 GBP 

Posts posted by Mythli

  1. WAD is a very old emulator supporting patch 1.x if you want to call it so (it is more about playing with the wow world) for more info read http://www.gotwow.ic.cz/wowd/

    "Database" files in WAD look like this:

    #include scripts/extra/creatures_auctioneers.scp
    ...
    #include scripts/afg/afgcreatures.scp
    #include scripts/afg/afgqiraj.scp
    #include scripts/chronos/chronos_vendors.scp
    #include scripts/chronos/chronos_creatures.scp
    
    [creature 0]
    name=Spawn Points (Only GM can see it)
    faction=35
    level=255
    attack=2000 2200
    bounding_radius=1.5
    combat_reach=2.25
    damage=0 2
    maxhealth=56
    model=262
    size=0.5
    type=1
    maxmana=0
    money=127500
    
    [creature 1]
    name=Spawn Point (Only GM can see it)
    faction=35
    level=255
    attack=2000 2200
    bounding_radius=1.5
    combat_reach=2.25
    damage=0 2
    maxhealth=56
    model=262
    size=0.5
    type=1
    maxmana=0
    money=127500

  2. I have written this tool long time ago for personal use and learning reasons (first c# programm i have ever wrote)

    SQLUpdate Merging Tool

    This is my little tool for merging various sql-updates to one big update.

    i have written this in .net (c#) but dont look at the code it's horrible

    Features:

    1. Support SD2, Mangos, UDB and many other SQL Update formats

    ^\\\\d+_{1}(\\\\d+)_{1}\\\\d+_{1}([A-Z]|[a-z]+)_{1}(.*)$", //match mangos update style (provide revision number, databasename, tablename)
    ^r{1}(\\\\d+)_{1}(\\\\w+).*$", //match SD2 Update style with some on official style (provide revision number& database name) 
    ^r{1}(\\\\d+)_{1}(.*)$", //match SD2 update style (provide revision number& database name)

    2. Grouping

    3. Editing

    4. Drag& Drop

    5. Apply filter

    Screenshots& Explanation:

    4bf568aecc65a_apply_filter_sqlmerge.PNG

    Feel free to comment this tool/ post feedback.

    regards Mythli <3

    Download: http://mythli.ath.cx/websvn/wsvn/Downloads/sqlupdatemerge_1.0/?op=dl&isdir=1&

    Changelog: http://mythli.ath.cx/websvn/wsvn/sqlMerge/trunk/?op=log&isdir=1&

    RSS: http://mythli.ath.cx/websvn/wsvn/sqlMerge/trunk/?op=rss&isdir=1&

    requires .net framework 2.0 or newest mono release.

  3. In the hope someone find this snippet usefull

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using System.IO;
    using System.Text.RegularExpressions;
    using System.Data;
    
    namespace scpparser.Classes
    {
       public class ScpParser
       {
           public String IncludeRoot;
           public String FileName;
           public List<String> ParsedFiles = new List<String>();
    
           private Regex IncludeSearchPattern = new Regex("^(?!//)#include\\\\s*(.*)");
           private Regex SectionStartSearchPattern = new Regex("^(?!//)\\\\[(\\\\w+)\\\\s*([^]]+)\\\\]$");
           private Regex ValuePairSearchPattern = new Regex("^(?!//)(\\\\w+)\\\\s*=\\\\s*(.*)$");
    
           private String currentSection;
           private String currentPrimaryKey;
    
           public Dictionary<String, Dictionary<String, List<String>>> ParseResult = new Dictionary<String, Dictionary<String, List<String>>>();
           public Dictionary<String, String> ParsedColumns = new Dictionary<String, String>();
    
           public ScpParser()
           {
           }
    
           public ScpParser(String IncludeRoot, String FileName) : this()
           {
               this.Open(IncludeRoot, FileName);
           }
    
           public void HandleInclude(String FileName)
           {
               FileName = Path.Combine(this.IncludeRoot, FileName);
               this.ParseFile(FileName);
           }
    
           public void HandleSection(String SectionName, String PrimaryKey)
           {
               this.currentSection = SectionName;
               this.currentPrimaryKey = PrimaryKey;
               this.ParseResult.Add(PrimaryKey, new Dictionary<String, List<String>>());
           }
    
           public void HandleValuePair(String ValueName, String Value)
           {
               if (String.IsNullOrEmpty(this.currentSection) || String.IsNullOrEmpty(this.currentPrimaryKey))
                   return;
    
               if (!this.ParseResult[this.currentPrimaryKey].ContainsKey(ValueName))
               {
                   this.ParseResult[this.currentPrimaryKey].Add(ValueName, new List<String>());
               }
    
               if (!this.ParsedColumns.ContainsKey(ValueName))
                   this.ParsedColumns.Add(ValueName, "");
    
               this.ParseResult[this.currentPrimaryKey][ValueName].Add(Value);
           }
    
           public void ParseLine(String Line)
           {
               Match match = null;
               match = this.IncludeSearchPattern.Match(Line);
               if (match.Success)
               {
                   this.HandleInclude(match.Groups[1].Value);
                   return;
               }
               match = this.SectionStartSearchPattern.Match(Line);
               if (match.Success)
               {
                   this.HandleSection(match.Groups[1].Value, match.Groups[2].Value);
                   return;
               }
               match = this.ValuePairSearchPattern.Match(Line);
               if (match.Success)
               {
                   this.HandleValuePair(match.Groups[1].Value, match.Groups[2].Value);
                   return;
               }
           }
    
           public void ParseFile(String FileName)
           {
    
               using (StreamReader fStream = File.OpenText(FileName))
               {
                   String line;
                   while ((line = fStream.ReadLine()) != null)
                   {
                       this.ParseLine(line);
                   }
               }
    
               this.ParsedFiles.Add(FileName);
           }
    
           public void Open(String IncludeRoot, String FileName)
           {
               this.IncludeRoot = IncludeRoot;
               this.FileName = FileName;
               this.ParseFile(FileName);
           }
       }
    }
    

  4. Well from what i gather with 2 min google, something like this should work too, no?

    vector<string> text;
    string line;
    ifstream textstream ("config.txt");
    while (getline(textstream, line)) {
      text.push_back(line);
    }
    textstream.close();
    for (int i=0; i < text.size(); i++)
      parseline(text[i]);
    

    look at my source, i don't make anything different.

  5. edit: It seems that "searchPattern" is indeed a compiled regexp.

    that's true

    and...

    I have already said that this was just programmed for learning reasons so sscanf(..) is faster and i never said that regular expressions make the performance boost

    if we look at the code

    while(std::getline(this->fileStream, line)) 
    {
        parselinehere(line);
    }

    would end in:

    * read line from file

    * parse line

    * waiting for parsing line to read next line

    until all lines are parsed

    with multiple threads we can read lines without waiting for parsing - on my hardware reading lines is very fast (ssd) and parsing lines is the time consuming thing. With multiple threads and a line buffer we can reduce the overhead to a minimum.

  6. And it makes things clearer when you don't prepend member stuff with m_ I guess.
    i started programming with c++ a few weeks ago but i still think this is a good thing ("this->) "logical divide" member and local variables like m_ do.
    Performance does matter, especially when you think about the .reload config command

    we are talking about 100-200ms or something around ;)

  7. I've programmed this for learning reasons and i need some feedback (coding style, correct pointers, ...)

    this codesnip will parse mangos-like configuration files using regular expressions and multiple threads (you need the boost c++ libary to compile)

    On a AMD Phenom x4 945 (+intel ssd) this code is up to 20 times faster in parsing than the dotconfpp mangos configuration class i don't think performance matter if we parse configuration files but this is still an interesting fact.

    here is my code:

    header-file:

    #ifndef CONFIG_H
    #define CONFIG_H
    
    #include "Common.h"
    #include <fstream>
    #include <boost/regex.hpp>
    
    class Config {
    public:
       Config(std::string ConfigFileName);
       void ReloadConfig();
       std::string GetStringDefault(std::string Name, std::string DefaultValue = "");
       bool GetBoolDefault(std::string Name, bool DefaultValue = false);
       int GetIntDefault(std::string Name, int DefaultValue = 0);
       float GetFloatDefault(std::string Name, float DefaultValue = 0);
    
       std::string GetFileName()
       {
           return this->configFileName;
       }
       ~Config();
    private:
       std::string configFileName;
       std::ifstream fileStream;
       boost::regex searchPattern;
       stringMapType configMap;
    
       //--used for threading
       boost::mutex lineBufferMutex;
       boost::mutex configMapMutex;
       std::list<std::string> lineBuffer;
       bool isFileFinish;
       void lineParser();
       //--
    };
    #endif

    code-file:

    #include "Config.h"
    
    Config::Config(std::string ConfigFileName) {
       this->configFileName = ConfigFileName;
    
       this->fileStream.open(this->configFileName);
       if (this->fileStream.is_open()) {
           this->searchPattern = boost::regex("^([ \\\\t]+)?([^#][^\\\\s]+)\\\\s*=\\\\s*(?\\\\d+)|(?:\\"([^\\"]*)\\")).*$");
           this->ReloadConfig();
       }
    }
    
    void Config::lineParser()
    {
       //--keep thread alive until file is fully pushed into lineBuffer and lineBuffer is empty
       while(this->isFileFinish == false || this->lineBuffer.size() != 0)
       {
           //--wait until lines for parsing are avaible
           if (this->lineBuffer.size() == 0)
               boost::this_thread::sleep(boost::Posix_time::millisec(1));
           //--
           else
           {
               boost::match_results<std::string::const_iterator> matches;
               //--lock lineBuffer object
               this->lineBufferMutex.lock();
               //copy first line into temp var
               std::string line = *this->lineBuffer.begin();
    
               //remove first line from lineBuffer
               this->lineBuffer.pop_front();
               this->lineBufferMutex.unlock();
               //--
    
               if (boost::regex_match(line, matches, this->searchPattern))
               {
                   //--insert match into our configMap (we have to lock our configMap object first)
                   this->configMapMutex.lock();
                   if (matches[3].matched)
                       //insert number (without qoutes)
                       this->configMap.insert(std::make_pair(matches[2], matches[3]));
                   else
                       //insert string (in quoutes)
                       this->configMap.insert(std::make_pair(matches[2], matches[4]));
                   this->configMapMutex.unlock();
                   //--
               }
           }
           //--
       }
    }
    
    void Config::ReloadConfig() {
       //--reset
       this->configMap.clear();
       this->fileStream.seekg(0, ios::beg);
       this->isFileFinish = false;
       //--
    
       //--define variables
       std::string line;
       boost::thread_group threadPool;
       //--
    
       //--create parser-threads for each logical cpu
       for(uint32 i = 0; i <  boost::thread::hardware_concurrency(); i++)
       {
           threadPool.create_thread(boost::bind(&Config::lineParser, this));
       }
       //--
    
       //--push lines from file in our lineBuffer
       while(std::getline(this->fileStream, line)) 
       {
           this->lineBuffer.push_back(line);
       }
       //--
       this->isFileFinish = true;
       //wait until all lines are parsed
       threadPool.join_all();
    }
    
    std::string Config::GetStringDefault(std::string Name, std::string DefaultValue)
    {
       stringMapType::const_iterator configNode = this->configMap.find(Name);
       if(configNode != this->configMap.end())
           return configNode->second;
       else
           return DefaultValue;
    }
    
    bool Config::GetBoolDefault(std::string Name, bool DefaultValue) 
    {
       std::string baseValue = this->GetStringDefault(Name, "");
       if (baseValue == "")
           return DefaultValue;
       else
           return boost::lexical_cast<bool>(baseValue);
    }
    int Config::GetIntDefault(std::string Name, int DefaultValue)
    {
       std::string baseValue = this->GetStringDefault(Name, "");
       if (baseValue == "")
           return DefaultValue;
       else 
           return boost::lexical_cast<int>(baseValue);
    }
    
    float Config::GetFloatDefault(std::string Name, float DefaultValue)
    {
       std::string baseValue = this->GetStringDefault(Name, "");
       if (baseValue == "")
           return DefaultValue;
       else 
           return boost::lexical_cast<float>(baseValue);
    }
    
    Config::~Config() {
       this->fileStream.close();
    }

  8. public class DotConfParser : Dictionary<String, String>
       {
           public DotConfParser() :base() {}
           public DotConfParser(String FileName)
           {
               this.configFileName = FileName;
               this.Reload();
           }
    
           public void Reload()
           {
               using (StreamReader streamReader = new StreamReader(File.OpenRead(this.configFileName)))
               {
                   while (!streamReader.EndOfStream)
                   {
                       Match match = this.searchPattern.Match(streamReader.ReadLine());
                       if (match.Success)
                           if (!base.ContainsKey(match.Groups[2].Value))
                               base.Add(match.Groups[2].Value, match.Groups[3].Value.Trim('"'));
                   }
               }
           }
           private String configFileName;
           private Regex searchPattern = new Regex(@"^([ \\\\t]+)?([^#].+)\\\\s*=\\\\s*(?\\\\d)|(?:\\"([^\\"]*)\\")).*$", RegexOptions.Compiled | RegexOptions.Multiline);
       }
    

    A c# class to read mangos configuration files.

    Enjoy.

  9. If you look at DBCReader.cs you will see that there is no detection:

    for (int r = 0; r < header.RecordsCount; ++r)
                   {
                       uint key = reader.ReadUInt32();
                       reader.BaseStream.Position -= 4;
    
                       T T_entry = reader.ReadStruct<T>();
    
                       dict.Add(key, T_entry);
                   }

    He try to read a struct from DBCFile with predefined types, structure of Spell.dbc is defined in "Structure.cs" -

    this is exactly that what i don't want.

  10. I have done some research on mangos code (DBCLoader) and figured out that you have string-reference fields which contain a Int32 value that point to a string with the following offset:

    StrReadOffset = StringStartOffset + FieldValue

    Problem now is that i have to detect if column is a string reference or not.

  11. Today i want to figure out how to read DBC files with c# so i started programming and i wonder how i can read Strings properly (assign them to "Rows") and how to detect and remove empty columns (columns that just have "0"-Values) like many DBC-Editors do

    Here is my Source:

    (Pastebin)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Windows.Forms;
    
    /* --DBC FILE STRUCTURE--
    [Header]
    Column      Field         Type         Notes
    1          Signature     String         (4-bytes) string, always 'WDBC'
    2          Records     Integer     (4-bytes) number of records in the file
    3          Fields     Integer     (4-bytes) number of fields per record
    4          Record     Size         Integer (4-bytes) Fields*FieldSize (FieldSize is usually 4, but not always)
    5          String     Block Size     Integer Size of the string block
    */
    
    namespace VisualAI.Classes.World.Data
    {
       enum DBCFileDefines
       {
           SIGNATURE_LENGTH = 4,
           FIELD_SIZE = 4,
           HEADER_SIZE = 20,
       }
    
       class DBCFileInfo
       {
           public Int32 pRecordCount;
           public Int32 pFieldCount;
    
    
           public Int32 pRecordSize;      //unused
           public Int32 pStringBlockSize; //unused
    
           public Int32 pStringBlockStart;
    
           public DBCFileInfo() { }
           public DBCFileInfo(Int32 pRowCount, Int32 pColumnCount)
           {
               this.pRecordCount = pRowCount;
               this.pFieldCount = pColumnCount;
    
               this.pStringBlockStart = (pRowCount * pColumnCount * (Int32)DBCFileDefines.FIELD_SIZE) + (Int32)DBCFileDefines.HEADER_SIZE +1;
           }
       }
    
       class DBCParser
       {
           private BinaryReader lBinaryReader;
           public String pFileName;
           public DBCFileInfo pDBCFileInfo = new DBCFileInfo();
    
           private Int32 lCurrentRecordId = -1;
    
           private void lLoadDBCFile()
           {
               this.lBinaryReader = new BinaryReader(File.Open(this.pFileName, FileMode.Open));
    
               UTF8Encoding lUTF8Encoder = new UTF8Encoding();
               //should read string WDBC if file is a valid DBC file
               String lSignature= lUTF8Encoder.GetString(this.lBinaryReader.ReadBytes((Int32)DBCFileDefines.FIELD_SIZE));
               if (lSignature != "WDBC")
                   throw new Exception("DBCParser only read WDBC-Files!");
               //after this we are @byte12
               this.pDBCFileInfo = new DBCFileInfo(this.lBinaryReader.ReadInt32(), this.lBinaryReader.ReadInt32());
    
               //unused
               this.pDBCFileInfo.pRecordSize = this.lBinaryReader.ReadInt32();
               this.pDBCFileInfo.pStringBlockSize = this.lBinaryReader.ReadInt32();
           }
    
           private Boolean lCheckForStringTerminator(Byte pByte)
           {
               if ((Int32)pByte != 0)
                   return false;
               else
                   return true;
           }
    
           public DBCParser(String pFileName)
           {
               this.pFileName = pFileName;
               this.lLoadDBCFile();
           }
    
           #region misc functions
           public List<String> pGetColumnList(String pPrefix)
           {
               List<String> lTmpColumnList = new List<String>();
               for (int i = 0; i < this.pDBCFileInfo.pFieldCount; i++)
               {
                   lTmpColumnList.Add(pPrefix + i);
               }
               return lTmpColumnList;
           }
           #endregion
    
           public Boolean pNextRecord()
           {
              while (this.lCurrentRecordId < this.pDBCFileInfo.pRecordCount-1)
              {
                  this.lCurrentRecordId++; 
                  return true;
               }
               return false;
           }
    
           #region Read-Based functions
           public Object pGetFieldValue(Int32 pFieldId)
           {
               if (pFieldId <= this.pDBCFileInfo.pFieldCount)
               {
                   Int64 lCurrentOffset = (Int32)DBCFileDefines.HEADER_SIZE + (this.lCurrentRecordId * (Int32)DBCFileDefines.FIELD_SIZE * this.pDBCFileInfo.pFieldCount + pFieldId);
                   this.lBinaryReader.BaseStream.Seek(lCurrentOffset, SeekOrigin.Begin);
    
                   return this.lBinaryReader.Read();
               }
               else
                   throw new Exception("Unknown Column!");
           }
    
           public Int32 pGetInt32(Int32 pFieldId)
           {
               return Convert.ToInt32(this.pGetFieldValue(pFieldId).ToString());
           }
    
           public String pGetStringValue(Int32 pFieldId)
           {
               // this.pStringBlockStart = (pRowCount * pColumnCount * (Int32)DBCFileDefines.FIELD_SIZE) + (Int32)DBCFileDefines.HEADER_SIZE + 1;
               Int64 lCurrentOffset = this.pDBCFileInfo.pStringBlockStart;
    
               this.lBinaryReader.BaseStream.Seek(lCurrentOffset, SeekOrigin.Begin);
    
               Int32 lStringDataLength = (Int32)(this.lBinaryReader.BaseStream.Length - (Int64)lCurrentOffset);
               Byte[] lStringData = this.lBinaryReader.ReadBytes(lStringDataLength);
               List<Byte> lBytes = new List<Byte>();
               Int32 lCurrentStringIT = 0;
    
               for (int i = 0; i < lStringData.Length; i++)
               {
                   Byte lCurrentByte = lStringData[i];
                   if (this.lCheckForStringTerminator(lCurrentByte))
                   {
                       Byte[] lStrByteArr = lBytes.ToArray();
                       UnicodeEncoding lUTF8Encoder = new UnicodeEncoding();
    
                       if (lCurrentStringIT >= pFieldId)
                           return lUTF8Encoder.GetString(lStrByteArr);
                       else
                       {
                           lCurrentStringIT++;
                           lBytes.Clear();
                       }
                   }
                   else
                   {
                       lBytes.Add(lCurrentByte);
                   }
               }
               return "";
           }
           #endregion
           public void pClose()
           {
               this.lBinaryReader.Close();
           }
       }
    }
    
    

    Example reading data from Map.dbc:

    (Pastebin)

    public static List<MapData> pGetMapList()
           {
               List<MapData> lTmpMapDataList = new List<MapData>();
               DBCParser lDBCParser = new DBCParser(Settings.Instance.pDBCPath + "/Map.dbc");
               Int32 i = 0;
    
               while (lDBCParser.pNextRecord())
               {
                   MapData lTmpMapData = new MapData();
                   lTmpMapData.pID = lDBCParser.pGetInt32(0);
                   lTmpMapData.pName = lDBCParser.pGetStringValue(i);
    
                   lTmpMapDataList.Add(lTmpMapData);
                   i++;
               }
    
               return lTmpMapDataList;
    
           }

    Reading Strings work just "fine" but i can't assign them to rows because i just have many strings one after one without any logical "order" (in my eyes).

    My code in "GetStringValue" is working but 100% no solution because it exponential take longer if you want to select a entry in a column/row (also a problem i can't assign string values to rows) in reason i always have to loop through all bytes, count existing strings and return the right one because i cant (?) set a pointer to specific string value.

    Any suggestions?

  12. Trinity include lots of code-hacks and unclean code in my opinion trinity will fail in all soon.

    if you want to have a stable server which is forward looking choose mangos, for now trinity has less bugs that are spell related and some realy nice additional features for developpers - it's your choice.

    My choice is ManGOS (which trinity is based on) for several important reasons.

  13. A role-based right system only have benefits because you can just do "the old thing"

    I'm a Web-developper, all things that our company manage or developp have role based right management because it's more flexible, stable and comfortable for us and our customers.

    Maybe someone who has the time and skill to implement this very nice feature will read this thread and start developping.

    Mythli<3

  14. This is my little tool for merging various sql-updates to one big update.

    i have written this in .net (c#) but dont look at the code it's horrible ;)

    Features:

    * Support SD2, Mangos, UDB and many other SQL Update formats

               "^\\\\d+_{1}(\\\\d+)_{1}\\\\d+_{1}([A-Z]|[a-z]+)_{1}(.*)$",     //match mangos update style (provide revision number, databasename, tablename)
               "^r{1}(\\\\d+)_{1}(\\\\w+).*$",                               //match SD2 Update style with some on official style (provide revision number& database name)   
               "^r{1}(\\\\d+)_{1}(.*)$",                                   //match SD2 update style (provide revision number& database name)
    

    * Grouping

    * Editing

    * Drag& Drop

    * Apply filter

    Screenshots& Explanation:

    updatenkn.png

    Feel free to comment this tool/ post feedback.

    regards Mythli <3

    Source: http://filebeam.com/6bd3af107f09ff920c44be5dd3779862

    Binary: http://filebeam.com/40a671bbe6924adbaa694dfab3863ee7

    requires .net framework 2.0 or newest mono release.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use