diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 33b5778..c19a894 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,4 +14,5 @@ add_subdirectory(SpeedTreeLib) add_subdirectory(SphereLib) add_subdirectory(UserInterface) add_subdirectory(PackMaker) +add_subdirectory(DumpProto) add_subdirectory(PackLib) diff --git a/src/DumpProto/CMakeLists.txt b/src/DumpProto/CMakeLists.txt new file mode 100644 index 0000000..19db608 --- /dev/null +++ b/src/DumpProto/CMakeLists.txt @@ -0,0 +1,10 @@ +file(GLOB_RECURSE FILE_SOURCES "*.h" "*.c" "*.cpp") + +add_executable(DumpProto ${FILE_SOURCES}) +set_target_properties(DumpProto PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +target_link_libraries(DumpProto + lzo2 +) \ No newline at end of file diff --git a/src/DumpProto/CsvFile.cpp b/src/DumpProto/CsvFile.cpp new file mode 100644 index 0000000..8c0d85c --- /dev/null +++ b/src/DumpProto/CsvFile.cpp @@ -0,0 +1,432 @@ +#include "CsvFile.h" +#include +#include + +#ifndef Assert + #include + #define Assert assert + #define LogToFile (void)(0); +#endif + +namespace +{ + /// �Ľ̿� state ���� + enum ParseState + { + STATE_NORMAL = 0, ///< �Ϲ� ���� + STATE_QUOTE ///< ����ǥ ���� ���� + }; + + /// ���ڿ� �¿��� ������ �����ؼ� ��ȯ�Ѵ�. + std::string Trim(std::string str) + { + str = str.erase(str.find_last_not_of(" \t\r\n") + 1); + str = str.erase(0, str.find_first_not_of(" \t\r\n")); + return str; + } + + /// \brief �־��� ���忡 �ִ� ����� ��� �ҹ��ڷ� �ٲ۴�. + std::string Lower(std::string original) + { + std::transform(original.begin(), original.end(), original.begin(), tolower); + return original; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ���� �׼����� ��, ���� ��� ����� �̸��� ����Ѵ�. +/// \param name �� �̸� +/// \param index �� ��� +//////////////////////////////////////////////////////////////////////////////// +void cCsvAlias::AddAlias(const char* name, size_t index) +{ + std::string converted(Lower(name)); + + Assert(m_Name2Index.find(converted) == m_Name2Index.end()); + Assert(m_Index2Name.find(index) == m_Index2Name.end()); + + m_Name2Index.insert(NAME2INDEX_MAP::value_type(converted, index)); + m_Index2Name.insert(INDEX2NAME_MAP::value_type(index, name)); +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ��� �����͸� �����Ѵ�. +//////////////////////////////////////////////////////////////////////////////// +void cCsvAlias::Destroy() +{ + m_Name2Index.clear(); + m_Index2Name.clear(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ���� ����� �̸����� ��ȯ�Ѵ�. +/// \param index ���� ��� +/// \return const char* �̸� +//////////////////////////////////////////////////////////////////////////////// +const char* cCsvAlias::operator [] (size_t index) const +{ + INDEX2NAME_MAP::const_iterator itr(m_Index2Name.find(index)); + if (itr == m_Index2Name.end()) + { + LogToFile(NULL, "cannot find suitable conversion for %d", index); + Assert(false && "cannot find suitable conversion"); + return NULL; + } + + return itr->second.c_str(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief �̸��� ���� ����� ��ȯ�Ѵ�. +/// \param name �̸� +/// \return size_t ���� ��� +//////////////////////////////////////////////////////////////////////////////// +size_t cCsvAlias::operator [] (const char* name) const +{ + NAME2INDEX_MAP::const_iterator itr(m_Name2Index.find(Lower(name))); + if (itr == m_Name2Index.end()) + { + LogToFile(NULL, "cannot find suitable conversion for %s", name); + Assert(false && "cannot find suitable conversion"); + return 0; + } + + return itr->second; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ������ �̸��� CSV ������ �ε��Ѵ�. +/// \param fileName CSV ���� �̸� +/// \param seperator �ʵ� �и��ڷ� ����� ����. �⺻���� ','�̴�. +/// \param quote ����ǥ�� ����� ����. �⺻���� '"'�̴�. +/// \return bool ������ �ε��ߴٸ� true, �ƴ϶�� false +//////////////////////////////////////////////////////////////////////////////// +bool cCsvFile::Load(const char* fileName, const char seperator, const char quote) +{ + Assert(seperator != quote); + + // Open file in binary mode to preserve UTF-8 encoding + std::ifstream file(fileName, std::ios::in | std::ios::binary); + if (!file) return false; + + Destroy(); // ������ �����͸� ���� + + cCsvRow* row = NULL; + ParseState state = STATE_NORMAL; + std::string token = ""; + char buf[2048+1] = {0,}; + + while (file.good()) + { + file.getline(buf, 2048); + buf[sizeof(buf)-1] = 0; + + std::string line(Trim(buf)); + if (line.empty() || (state == STATE_NORMAL && line[0] == '#')) continue; + + std::string text = std::string(line) + " "; // �Ľ� lookahead ������ �ٿ��ش�. + size_t cur = 0; + + while (cur < text.size()) + { + // ���� ��尡 QUOTE ����� ��, + if (state == STATE_QUOTE) + { + // '"' ������ ������ �� �����̴�. + // 1. �� ���ο� Ư�� ���ڰ� ���� ��� �̸� �˸��� �� �¿��� �� + // 2. �� ������ '"' ���ڰ� '"' 2���� ġȯ�� �� + // �� �� ù��° ����� ������ �ִ� ���� CSV ������ �������̶��, + // ������ STATE_NORMAL�� �ɸ��� �Ǿ��ִ�. + // �׷��Ƿ� ���⼭ �ɸ��� ���� 1���� ���� ��쳪, 2�� ��� ���̴�. + // 2���� ��쿡�� ������ '"' ���ڰ� 2���� ��Ÿ����. ������ 1���� + // ���� ��쿡�� �ƴϴ�. �̸� �������� �ؼ� �ڵ带 ¥��... + if (text[cur] == quote) + { + // ���� ���ڰ� '"' ���ڶ��, �� ���ӵ� '"' ���ڶ�� + // �̴� �� ������ '"' ���ڰ� ġȯ�� ���̴�. + if (text[cur+1] == quote) + { + token += quote; + ++cur; + } + // ���� ���ڰ� '"' ���ڰ� �ƴ϶�� + // ������ '"'���ڴ� ���� ���� �˸��� ���ڶ�� �� �� �ִ�. + else + { + state = STATE_NORMAL; + } + } + else + { + token += text[cur]; + } + } + // ���� ��尡 NORMAL ����� ��, + else if (state == STATE_NORMAL) + { + if (row == NULL) + row = new cCsvRow(); + + // ',' ���ڸ� �����ٸ� ���� ���� �ǹ��Ѵ�. + // ��ū���μ� �� ����Ʈ���ٰ� ����ְ�, ��ū�� �ʱ�ȭ�Ѵ�. + if (text[cur] == seperator) + { + row->push_back(token); + token.clear(); + } + // '"' ���ڸ� �����ٸ�, QUOTE ���� ��ȯ�Ѵ�. + else if (text[cur] == quote) + { + state = STATE_QUOTE; + } + // �ٸ� �Ϲ� ���ڶ�� ���� ��ū���ٰ� �����δ�. + else + { + token += text[cur]; + } + } + + ++cur; + } + + // ������ ���� ���� ',' ���ڰ� ���� ������ ���⼭ �߰�������Ѵ�. + // ��, �� �Ľ� lookahead ������ ���� �����̽� ���� �� ���� ����. + if (state == STATE_NORMAL) + { + Assert(row != NULL); + row->push_back(token.substr(0, token.size()-2)); + m_Rows.push_back(row); + token.clear(); + row = NULL; + } + else + { + token = token.substr(0, token.size()-2) + "\r\n"; + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ������ �ִ� ������ CSV ���Ͽ��� �����Ѵ�. +/// \param fileName CSV ���� �̸� +/// \param append true�� ���, ������ ���Ͽ��� �����δ�. false�� ��쿡�� +/// ������ ���� ������ �����ϰ�, ���� ����. +/// \param seperator �ʵ� �и��ڷ� ����� ����. �⺻���� ','�̴�. +/// \param quote ����ǥ�� ����� ����. �⺻���� '"'�̴�. +/// \return bool ������ �����ߴٸ� true, ������ ���� ��쿡�� false +//////////////////////////////////////////////////////////////////////////////// +bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quote) const +{ + Assert(seperator != quote); + + // ��� ��忡 ���� ������ ������ �÷��׷� �����Ѵ�. + std::ofstream file; + if (append) { file.open(fileName, std::ios::out | std::ios::app); } + else { file.open(fileName, std::ios::out | std::ios::trunc); } + + // ������ ���� ���ߴٸ�, false�� �����Ѵ�. + if (!file) return false; + + char special_chars[5] = { seperator, quote, '\r', '\n', 0 }; + char quote_escape_string[3] = { quote, quote, 0 }; + + // ��� ���� Ⱦ���ϸ鼭... + for (size_t i=0; isize(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ����� �̿��� int ������ �� ���� ��ȯ�Ѵ�. +/// \param index �� ��� +/// \return int �� �� +//////////////////////////////////////////////////////////////////////////////// +int cCsvTable::AsInt(size_t index) const +{ + const cCsvRow* const row = CurRow(); + Assert(row); + Assert(index < row->size()); + return row->AsInt(index); +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ����� �̿��� double ������ �� ���� ��ȯ�Ѵ�. +/// \param index �� ��� +/// \return double �� �� +//////////////////////////////////////////////////////////////////////////////// +double cCsvTable::AsDouble(size_t index) const +{ + const cCsvRow* const row = CurRow(); + Assert(row); + Assert(index < row->size()); + return row->AsDouble(index); +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ����� �̿��� std::string ������ �� ���� ��ȯ�Ѵ�. +/// \param index �� ��� +/// \return const char* �� �� +//////////////////////////////////////////////////////////////////////////////// +const char* cCsvTable::AsStringByIndex(size_t index) const +{ + const cCsvRow* const row = CurRow(); + Assert(row); + Assert(index < row->size()); + return row->AsString(index); +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief alias�� ������ ��� �����͸� �����Ѵ�. +//////////////////////////////////////////////////////////////////////////////// +void cCsvTable::Destroy() +{ + m_File.Destroy(); + m_Alias.Destroy(); + m_CurRow = -1; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ���� ���� ��ȯ�Ѵ�. +/// \return const cCsvRow* �׼����� ������ ���� ���� �����ϴ� ��쿡�� �� ���� +/// �����͸� ��ȯ�ϰ�, �� �̻� �׼��� ������ ���� ���� ��쿡�� NULL�� +/// ��ȯ�Ѵ�. +//////////////////////////////////////////////////////////////////////////////// +const cCsvRow* const cCsvTable::CurRow() const +{ + if (m_CurRow < 0) + { + Assert(false && "call Next() first!"); + return NULL; + } + else if (m_CurRow >= (int)m_File.GetRowCount()) + { + Assert(false && "no more rows!"); + return NULL; + } + + return m_File[m_CurRow]; +} + + + diff --git a/src/DumpProto/CsvFile.h b/src/DumpProto/CsvFile.h new file mode 100644 index 0000000..90c02c7 --- /dev/null +++ b/src/DumpProto/CsvFile.h @@ -0,0 +1,325 @@ +#ifndef __CSVFILE_H__ +#define __CSVFILE_H__ + +#include +#include + +#if _MSC_VER + //#include + #include +#else + #include +#endif + +//////////////////////////////////////////////////////////////////////////////// +/// \class cCsvAlias +/// \brief CSV ÆÄÀÏÀ» ¼öÁ¤ÇßÀ» ¶§ ¹ß»ýÇÏ´Â À妽º ¹®Á¦¸¦ ÁÙÀ̱â À§ÇÑ +/// º°¸í °´Ã¼. +/// +/// ¿¹¸¦ µé¾î 0¹ø Ä÷³ÀÌ A¿¡ °üÇÑ ³»¿ëÀ» Æ÷ÇÔÇϰí, 1¹ø Ä÷³ÀÌ B¿¡ °üÇÑ ³»¿ëÀ» +/// Æ÷ÇÔÇϰí ÀÖ¾ú´Âµ¥... +/// +///
+/// int a = row.AsInt(0);
+/// int b = row.AsInt(1);
+/// 
+/// +/// ±× »çÀÌ¿¡ C¿¡ °üÇÑ ³»¿ëÀ» Æ÷ÇÔÇÏ´Â Ä÷³ÀÌ ³¢¾îµç °æ¿ì, ÇϵåÄÚµùµÇ¾î ÀÖ´Â +/// 1¹øÀ» ã¾Æ¼­ °íÃÄ¾ß Çϴµ¥, »ó´çÈ÷ ¿¡·¯°¡ ¹ß»ýÇϱ⠽¬¿î ÀÛ¾÷ÀÌ´Ù. +/// +///
+/// int a = row.AsInt(0);
+/// int c = row.AsInt(1);
+/// int b = row.AsInt(2); <-- ÀÌ ºÎºÐÀ» ÀÏÀÏÀÌ ½Å°æ½á¾ß ÇÑ´Ù.
+/// 
+/// +/// ÀÌ ºÎºÐÀ» ¹®ÀÚ¿­·Î ó¸®Çϸé À¯Áöº¸¼ö¿¡ µé¾î°¡´Â ¼ö°í¸¦ ¾à°£À̳ª¸¶ ÁÙÀÏ ¼ö +/// ÀÖ´Ù. +//////////////////////////////////////////////////////////////////////////////// + +class cCsvAlias +{ +private: +#if _MSC_VER + //typedef stdext::hash_map NAME2INDEX_MAP; + //typedef stdext::hash_map INDEX2NAME_MAP; + typedef std::unordered_map NAME2INDEX_MAP; + typedef std::unordered_map INDEX2NAME_MAP; +#else + typedef std::map NAME2INDEX_MAP; + typedef std::map INDEX2NAME_MAP; +#endif + + NAME2INDEX_MAP m_Name2Index; ///< ¼¿ À妽º ´ë½ÅÀ¸·Î »ç¿ëÇϱâ À§ÇÑ À̸§µé + INDEX2NAME_MAP m_Index2Name; ///< À߸øµÈ alias¸¦ °Ë»çÇϱâ À§ÇÑ Ãß°¡ÀûÀÎ ¸Ê + + +public: + /// \brief »ý¼ºÀÚ + cCsvAlias() {} + + /// \brief ¼Ò¸êÀÚ + virtual ~cCsvAlias() {} + + +public: + /// \brief ¼¿À» ¾×¼¼½ºÇÒ ¶§, ¼ýÀÚ ´ë½Å »ç¿ëÇÒ À̸§À» µî·ÏÇÑ´Ù. + void AddAlias(const char* name, size_t index); + + /// \brief ¸ðµç µ¥ÀÌÅ͸¦ »èÁ¦ÇÑ´Ù. + void Destroy(); + + /// \brief ¼ýÀÚ À妽º¸¦ À̸§À¸·Î º¯È¯ÇÑ´Ù. + const char* operator [] (size_t index) const; + + /// \brief À̸§À» ¼ýÀÚ À妽º·Î º¯È¯ÇÑ´Ù. + size_t operator [] (const char* name) const; + + +private: + /// \brief º¹»ç »ý¼ºÀÚ ±ÝÁö + cCsvAlias(const cCsvAlias&) {} + + /// \brief ´ëÀÔ ¿¬»êÀÚ ±ÝÁö + const cCsvAlias& operator = (const cCsvAlias&) { return *this; } +}; + + +//////////////////////////////////////////////////////////////////////////////// +/// \class cCsvRow +/// \brief CSV ÆÄÀÏÀÇ ÇÑ ÇàÀ» ĸ½¶È­ÇÑ Å¬·¡½º +/// +/// CSVÀÇ ±âº» Æ÷¸ËÀº ¿¢¼¿¿¡¼­ º¸ÀÌ´Â ÇϳªÀÇ ¼¿À» ',' ¹®ÀÚ·Î ±¸ºÐÇÑ °ÍÀÌ´Ù. +/// ÇÏÁö¸¸, ¼¿ ¾È¿¡ Ư¼ö ¹®ÀÚ·Î ¾²ÀÌ´Â ',' ¹®ÀÚ³ª '"' ¹®ÀÚ°¡ µé¾î°¥ °æ¿ì, +/// ¸ð¾çÀÌ ¾à°£ ÀÌ»óÇÏ°Ô º¯ÇÑ´Ù. ´ÙÀ½Àº ±× º¯È­ÀÇ ¿¹ÀÌ´Ù. +/// +///
+/// ¿¢¼¿¿¡¼­ º¸ÀÌ´Â ¸ð¾ç | ½ÇÁ¦ CSV ÆÄÀÏ¿¡ µé¾î°¡ÀÖ´Â ¸ð¾ç
+/// ---------------------+----------------------------------------------------
+/// ItemPrice            | ItemPrice
+/// Item,Price           | "Item,Price"
+/// Item"Price           | "Item""Price"
+/// "ItemPrice"          | """ItemPrice"""
+/// "Item,Price"         | """Item,Price"""
+/// Item",Price          | "Item"",Price"
+/// 
+/// +/// ÀÌ ¿¹·Î¼­ ´ÙÀ½°ú °°Àº »çÇ×À» ¾Ë ¼ö ÀÖ´Ù. +/// - ¼¿ ³»ºÎ¿¡ ',' ¶Ç´Â '"' ¹®ÀÚ°¡ µé¾î°¥ °æ¿ì, ¼¿ Á¿쿡 '"' ¹®ÀÚ°¡ »ý±ä´Ù. +/// - ¼¿ ³»ºÎÀÇ '"' ¹®ÀÚ´Â 2°³·Î ġȯµÈ´Ù. +/// +/// \sa cCsvFile +//////////////////////////////////////////////////////////////////////////////// + +class cCsvRow : public std::vector +{ +public: + /// \brief ±âº» »ý¼ºÀÚ + cCsvRow() {} + + /// \brief ¼Ò¸êÀÚ + ~cCsvRow() {} + + +public: + /// \brief ÇØ´ç ¼¿ÀÇ µ¥ÀÌÅ͸¦ int ÇüÀ¸·Î ¹ÝȯÇÑ´Ù. + int AsInt(size_t index) const { return atoi(at(index).c_str()); } + + /// \brief ÇØ´ç ¼¿ÀÇ µ¥ÀÌÅ͸¦ double ÇüÀ¸·Î ¹ÝȯÇÑ´Ù. + double AsDouble(size_t index) const { return atof(at(index).c_str()); } + + /// \brief ÇØ´ç ¼¿ÀÇ µ¥ÀÌÅ͸¦ ¹®ÀÚ¿­·Î ¹ÝȯÇÑ´Ù. + const char* AsString(size_t index) const { return at(index).c_str(); } + + /// \brief ÇØ´çÇÏ´Â À̸§ÀÇ ¼¿ µ¥ÀÌÅ͸¦ int ÇüÀ¸·Î ¹ÝȯÇÑ´Ù. + int AsInt(const char* name, const cCsvAlias& alias) const { + return atoi( at(alias[name]).c_str() ); + } + + /// \brief ÇØ´çÇÏ´Â À̸§ÀÇ ¼¿ µ¥ÀÌÅ͸¦ int ÇüÀ¸·Î ¹ÝȯÇÑ´Ù. + double AsDouble(const char* name, const cCsvAlias& alias) const { + return atof( at(alias[name]).c_str() ); + } + + /// \brief ÇØ´çÇÏ´Â À̸§ÀÇ ¼¿ µ¥ÀÌÅ͸¦ ¹®ÀÚ¿­·Î ¹ÝȯÇÑ´Ù. + const char* AsString(const char* name, const cCsvAlias& alias) const { + return at(alias[name]).c_str(); + } + + +private: + /// \brief º¹»ç »ý¼ºÀÚ ±ÝÁö + cCsvRow(const cCsvRow&) {} + + /// \brief ´ëÀÔ ¿¬»êÀÚ ±ÝÁö + const cCsvRow& operator = (const cCsvRow&) { return *this; } +}; + + +//////////////////////////////////////////////////////////////////////////////// +/// \class cCsvFile +/// \brief CSV(Comma Seperated Values) ÆÄÀÏÀ» read/writeÇϱâ À§ÇÑ Å¬·¡½º +/// +/// sample +///
+/// cCsvFile file;
+///
+/// cCsvRow row1, row2, row3;
+/// row1.push_back("ItemPrice");
+/// row1.push_back("Item,Price");
+/// row1.push_back("Item\"Price");
+///
+/// row2.reserve(3);
+/// row2[0] = "\"ItemPrice\"";
+/// row2[1] = "\"Item,Price\"";
+/// row2[2] = "Item\",Price\"";
+///
+/// row3 = "\"ItemPrice\"\"Item,Price\"Item\",Price\"";
+///
+/// file.add(row1);
+/// file.add(row2);
+/// file.add(row3);
+/// file.save("test.csv", false);
+/// 
+/// +/// \todo ÆÄÀÏ¿¡¼­¸¸ ÀоîµéÀÏ °ÍÀÌ ¾Æ´Ï¶ó, ¸Þ¸ð¸® ¼Ò½º·ÎºÎÅÍ Àд ÇÔ¼öµµ +/// ÀÖ¾î¾ß ÇÒ µí ÇÏ´Ù. +//////////////////////////////////////////////////////////////////////////////// + +class cCsvFile +{ +private: + typedef std::vector ROWS; + + ROWS m_Rows; ///< Çà Ä÷º¼Ç + + +public: + /// \brief »ý¼ºÀÚ + cCsvFile() {} + + /// \brief ¼Ò¸êÀÚ + virtual ~cCsvFile() { Destroy(); } + + +public: + /// \brief ÁöÁ¤µÈ À̸§ÀÇ CSV ÆÄÀÏÀ» ·ÎµåÇÑ´Ù. + bool Load(const char* fileName, const char seperator=',', const char quote='"'); + + /// \brief °¡Áö°í ÀÖ´Â ³»¿ëÀ» CSV ÆÄÀÏ¿¡´Ù ÀúÀåÇÑ´Ù. + bool Save(const char* fileName, bool append=false, char seperator=',', char quote='"') const; + + /// \brief ¸ðµç µ¥ÀÌÅ͸¦ ¸Þ¸ð¸®¿¡¼­ »èÁ¦ÇÑ´Ù. + void Destroy(); + + /// \brief ÇØ´çÇÏ´Â À妽ºÀÇ ÇàÀ» ¹ÝȯÇÑ´Ù. + cCsvRow* operator [] (size_t index); + + /// \brief ÇØ´çÇÏ´Â À妽ºÀÇ ÇàÀ» ¹ÝȯÇÑ´Ù. + const cCsvRow* operator [] (size_t index) const; + + /// \brief ÇàÀÇ °¹¼ö¸¦ ¹ÝȯÇÑ´Ù. + size_t GetRowCount() const { return m_Rows.size(); } + + +private: + /// \brief º¹»ç »ý¼ºÀÚ ±ÝÁö + cCsvFile(const cCsvFile&) {} + + /// \brief ´ëÀÔ ¿¬»êÀÚ ±ÝÁö + const cCsvFile& operator = (const cCsvFile&) { return *this; } +}; + + +//////////////////////////////////////////////////////////////////////////////// +/// \class cCsvTable +/// \brief CSV ÆÄÀÏÀ» ÀÌ¿ëÇØ Å×ÀÌºí µ¥ÀÌÅ͸¦ ·ÎµåÇÏ´Â °æ¿ì°¡ ¸¹Àºµ¥, ÀÌ Å¬·¡½º´Â +/// ±× ÀÛ¾÷À» Á» ´õ ½±°Ô Çϱâ À§ÇØ ¸¸µç À¯Æ¿¸®Æ¼ Ŭ·¡½º´Ù. +/// +/// CSV ÆÄÀÏÀ» ·ÎµåÇÏ´Â °æ¿ì, ¼ýÀÚ¸¦ ÀÌ¿ëÇØ ¼¿À» ¾×¼¼½ºÇØ¾ß Çϴµ¥, CSV +/// ÆÄÀÏÀÇ Æ÷¸ËÀÌ ¹Ù²î´Â °æ¿ì, ÀÌ ¼ýÀÚµéÀ» º¯°æÇØÁà¾ßÇÑ´Ù. ÀÌ ÀÛ¾÷ÀÌ ²Ï +/// ½Å°æ ÁýÁßÀ» ¿ä±¸ÇÏ´Â µ¥´Ù°¡, ¿¡·¯°¡ ¹ß»ýÇϱ⠽±´Ù. ±×·¯¹Ç·Î ¼ýÀÚ·Î +/// ¾×¼¼½ºÇϱ⺸´Ù´Â ¹®ÀÚ¿­·Î ¾×¼¼½ºÇÏ´Â °ÍÀÌ ¾à°£ ´À¸®Áö¸¸ ³´´Ù°í ÇÒ ¼ö ÀÖ´Ù. +/// +/// sample +///
+/// cCsvTable table;
+///
+/// table.alias(0, "ItemClass");
+/// table.alias(1, "ItemType");
+///
+/// if (table.load("test.csv"))
+/// {
+///     while (table.next())
+///     {
+///         std::string item_class = table.AsString("ItemClass");
+///         int         item_type  = table.AsInt("ItemType"); 
+///     }
+/// }
+/// 
+//////////////////////////////////////////////////////////////////////////////// + +class cCsvTable +{ +public : + cCsvFile m_File; ///< CSV ÆÄÀÏ °´Ã¼ +private: + cCsvAlias m_Alias; ///< ¹®ÀÚ¿­À» ¼¿ À妽º·Î º¯È¯Çϱâ À§ÇÑ °´Ã¼ + int m_CurRow; ///< ÇöÀç Ⱦ´Ü ÁßÀÎ Çà ¹øÈ£ + + +public: + /// \brief »ý¼ºÀÚ + cCsvTable(); + + /// \brief ¼Ò¸êÀÚ + virtual ~cCsvTable(); + + +public: + /// \brief ÁöÁ¤µÈ À̸§ÀÇ CSV ÆÄÀÏÀ» ·ÎµåÇÑ´Ù. + bool Load(const char* fileName, const char seperator=',', const char quote='"'); + + /// \brief ¼¿À» ¾×¼¼½ºÇÒ ¶§, ¼ýÀÚ ´ë½Å »ç¿ëÇÒ À̸§À» µî·ÏÇÑ´Ù. + void AddAlias(const char* name, size_t index) { m_Alias.AddAlias(name, index); } + + /// \brief ´ÙÀ½ ÇàÀ¸·Î ³Ñ¾î°£´Ù. + bool Next(); + + /// \brief ÇöÀç ÇàÀÇ ¼¿ ¼ýÀÚ¸¦ ¹ÝȯÇÑ´Ù. + size_t ColCount() const; + + /// \brief À妽º¸¦ ÀÌ¿ëÇØ int ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. + int AsInt(size_t index) const; + + /// \brief À妽º¸¦ ÀÌ¿ëÇØ double ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. + double AsDouble(size_t index) const; + + /// \brief À妽º¸¦ ÀÌ¿ëÇØ std::string ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. + const char* AsStringByIndex(size_t index) const; + + /// \brief ¼¿ À̸§À» ÀÌ¿ëÇØ int ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. + int AsInt(const char* name) const { return AsInt(m_Alias[name]); } + + /// \brief ¼¿ À̸§À» ÀÌ¿ëÇØ double ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. + double AsDouble(const char* name) const { return AsDouble(m_Alias[name]); } + + /// \brief ¼¿ À̸§À» ÀÌ¿ëÇØ std::string ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. + const char* AsString(const char* name) const { return AsStringByIndex(m_Alias[name]); } + + /// \brief alias¸¦ Æ÷ÇÔÇØ ¸ðµç µ¥ÀÌÅ͸¦ »èÁ¦ÇÑ´Ù. + void Destroy(); + + +private: + /// \brief ÇöÀç ÇàÀ» ¹ÝȯÇÑ´Ù. + const cCsvRow* const CurRow() const; + + /// \brief º¹»ç »ý¼ºÀÚ ±ÝÁö + cCsvTable(const cCsvTable&) {} + + /// \brief ´ëÀÔ ¿¬»êÀÚ ±ÝÁö + const cCsvTable& operator = (const cCsvTable&) { return *this; } +}; + +#endif //__CSVFILE_H__ diff --git a/src/DumpProto/ItemCSVReader.cpp b/src/DumpProto/ItemCSVReader.cpp new file mode 100644 index 0000000..547d747 --- /dev/null +++ b/src/DumpProto/ItemCSVReader.cpp @@ -0,0 +1,566 @@ +#include +#include "ItemCSVReader.h" + + + +using namespace std; + +inline string trim_left(const string& str) +{ + string::size_type n = str.find_first_not_of(" \t\v\n\r"); + return n == string::npos ? str : str.substr(n, str.length()); +} + +inline string trim_right(const string& str) +{ + string::size_type n = str.find_last_not_of(" \t\v\n\r"); + return n == string::npos ? str : str.substr(0, n + 1); +} + +string trim(const string& str){return trim_left(trim_right(str));} + +static string* StringSplit(string strOrigin, string strTok) +{ + int cutAt; //ÀÚ¸£´ÂÀ§Ä¡ + int index = 0; //¹®ÀÚ¿­À妽º + string* strResult = new string[30]; //°á°úreturn ÇÒº¯¼ö + + //strTokÀ»Ã£À»¶§±îÁö¹Ýº¹ + while ((cutAt = strOrigin.find_first_of(strTok)) != strOrigin.npos) + { + if (cutAt > 0) //ÀÚ¸£´ÂÀ§Ä¡°¡0º¸´ÙÅ©¸é(¼º°ø½Ã) + { + strResult[index++] = strOrigin.substr(0, cutAt); //°á°ú¹è¿­¿¡Ãß°¡ + } + strOrigin = strOrigin.substr(cutAt+1); //¿øº»ÀºÀÚ¸¥ºÎºÐÁ¦¿ÜÇѳª¸ÓÁö + } + + if(strOrigin.length() > 0) //¿øº»À̾ÆÁ÷³²¾ÒÀ¸¸é + { + strResult[index++] = strOrigin.substr(0, cutAt); //³ª¸ÓÁö¸¦°á°ú¹è¿­¿¡Ãß°¡ + } + + for( int i=0;i "; + for (int j=0;j "; + for (int j=0;j " << retValue << endl; + + return retValue; +} + +int get_Item_Flag_Value(string inputString) +{ + + string arFlag[] = {"ITEM_TUNABLE", "ITEM_SAVE", "ITEM_STACKABLE", "COUNT_PER_1GOLD", "ITEM_SLOW_QUERY", "ITEM_UNIQUE", + "ITEM_MAKECOUNT", "ITEM_IRREMOVABLE", "CONFIRM_WHEN_USE", "QUEST_USE", "QUEST_USE_MULTIPLE", + "QUEST_GIVE", "ITEM_QUEST", "LOG", "STACKABLE", "SLOW_QUERY", "REFINEABLE", "IRREMOVABLE", "ITEM_APPLICABLE"}; + + + int retValue = 0; + string* arInputString = StringSplit(inputString, "|"); //ÇÁ·ÎÅä Á¤º¸ ³»¿ëÀ» ´Ü¾îº°·Î Âɰµ ¹è¿­. + for(int i =0;i " << retValue << endl; + + return retValue; +} + +int get_Item_WearFlag_Value(string inputString) +{ + + string arWearrFlag[] = {"WEAR_BODY", "WEAR_HEAD", "WEAR_FOOTS", "WEAR_WRIST", "WEAR_WEAPON", "WEAR_NECK", "WEAR_EAR", "WEAR_SHIELD", "WEAR_UNIQUE", + "WEAR_ARROW", "WEAR_HAIR", "WEAR_ABILITY"}; + + + int retValue = 0; + string* arInputString = StringSplit(inputString, "|"); //ÇÁ·ÎÅä Á¤º¸ ³»¿ëÀ» ´Ü¾îº°·Î Âɰµ ¹è¿­. + for(int i =0;i " << retValue << endl; + + return retValue; +} + +int get_Item_Immune_Value(string inputString) +{ + + string arImmune[] = {"PARA","CURSE","STUN","SLEEP","SLOW","POISON","TERROR"}; + + int retValue = 0; + string* arInputString = StringSplit(inputString, "|"); //ÇÁ·ÎÅä Á¤º¸ ³»¿ëÀ» ´Ü¾îº°·Î Âɰµ ¹è¿­. + for(int i =0;i " << retValue << endl; + + return retValue; +} + + + + +int get_Item_LimitType_Value(string inputString) +{ + string arLimitType[] = {"LIMIT_NONE", "LEVEL", "STR", "DEX", "INT", "CON", "PC_BANG", "REAL_TIME", "REAL_TIME_FIRST_USE", "TIMER_BASED_ON_WEAR"}; + + int retInt = -1; + //cout << "LimitType : " << limitTypeStr << " -> "; + for (int j=0;j "; + for (int j=0;j "; + for (int j=0;j "; + for (int j=0;j "; + for (int j=0;j "; + for (int j=0;j " << retValue << endl; + + return retValue; +} +int get_Mob_RaceFlag_Value(string inputString) +{ + string arRaceFlag[] = {"ANIMAL","UNDEAD","DEVIL","HUMAN","ORC","MILGYO","INSECT","FIRE","ICE","DESERT","TREE", + "ATT_ELEC","ATT_FIRE","ATT_ICE","ATT_WIND","ATT_EARTH","ATT_DARK"}; + + int retValue = 0; + string* arInputString = StringSplit(inputString, "|"); //ÇÁ·ÎÅä Á¤º¸ ³»¿ëÀ» ´Ü¾îº°·Î Âɰµ ¹è¿­. + for(int i =0;i " << retValue << endl; + + return retValue; +} +int get_Mob_ImmuneFlag_Value(string inputString) +{ + string arImmuneFlag[] = {"STUN","SLOW","FALL","CURSE","POISON","TERROR"}; + + int retValue = 0; + string* arInputString = StringSplit(inputString, ","); //ÇÁ·ÎÅä Á¤º¸ ³»¿ëÀ» ´Ü¾îº°·Î Âɰµ ¹è¿­. + for(int i =0;i " << retValue << endl; + + + return retValue; +} diff --git a/src/DumpProto/ItemCSVReader.h b/src/DumpProto/ItemCSVReader.h new file mode 100644 index 0000000..94d6ce0 --- /dev/null +++ b/src/DumpProto/ItemCSVReader.h @@ -0,0 +1,29 @@ +#ifndef __Item_CSV_READER_H__ +#define __Item_CSV_READER_H__ + +#include + +//csv ÆÄÀÏÀ» Àоî¿Í¼­ ¾ÆÀÌÅÛ Å×ÀÌºí¿¡ ³Ö¾îÁØ´Ù. +void putItemIntoTable(); //(Å×À̺í, Å×½ºÆ®¿©ºÎ) + +int get_Item_Type_Value(std::string inputString); +int get_Item_SubType_Value(int type_value, std::string inputString); +int get_Item_AntiFlag_Value(std::string inputString); +int get_Item_Flag_Value(std::string inputString); +int get_Item_WearFlag_Value(std::string inputString); +int get_Item_Immune_Value(std::string inputString); +int get_Item_LimitType_Value(std::string inputString); +int get_Item_ApplyType_Value(std::string inputString); + + +//¸ó½ºÅÍ ÇÁ·ÎÅäµµ ÀÐÀ» ¼ö ÀÖ´Ù. +int get_Mob_Rank_Value(std::string inputString); +int get_Mob_Type_Value(std::string inputString); +int get_Mob_BattleType_Value(std::string inputString); + +int get_Mob_Size_Value(std::string inputString); +int get_Mob_AIFlag_Value(std::string inputString); +int get_Mob_RaceFlag_Value(std::string inputString); +int get_Mob_ImmuneFlag_Value(std::string inputString); + +#endif \ No newline at end of file diff --git a/src/DumpProto/Singleton.h b/src/DumpProto/Singleton.h new file mode 100644 index 0000000..e5d118c --- /dev/null +++ b/src/DumpProto/Singleton.h @@ -0,0 +1,112 @@ +#ifndef __INC_ETERLIB_SINGLETON_H__ +#define __INC_ETERLIB_SINGLETON_H__ + +#include + +template class CSingleton +{ + static T * ms_singleton; + +public: + CSingleton() + { + assert(!ms_singleton); + ms_singleton = (T*) this; + } + + virtual ~CSingleton() + { + assert(ms_singleton); + ms_singleton = 0; + } + + __forceinline static T & Instance() + { + assert(ms_singleton); + return (*ms_singleton); + } + + __forceinline static T * InstancePtr() + { + return (ms_singleton); + } + + __forceinline static T & instance() + { + assert(ms_singleton); + return (*ms_singleton); + } +}; + +template T * CSingleton ::ms_singleton = 0; + +// +// singleton for non-hungarian +// +template class singleton +{ + static T * ms_singleton; + +public: + singleton() + { + assert(!ms_singleton); + ms_singleton = (T*) this; + } + + virtual ~singleton() + { + assert(ms_singleton); + ms_singleton = 0; + } + + __forceinline static T & Instance() + { + assert(ms_singleton); + return (*ms_singleton); + } + + __forceinline static T * InstancePtr() + { + return (ms_singleton); + } + + __forceinline static T & instance() + { + assert(ms_singleton); + return (*ms_singleton); + } +}; + +template T * singleton ::ms_singleton = 0; + +/* +template +class CSingleton : public T +{ + public: + static T & Instance() + { + assert(ms_pInstance != NULL); + return *ms_pInstance; + } + + CSingleton() + { + assert(ms_pInstance == NULL); + ms_pInstance = this; + } + + virtual ~CSingleton() + { + assert(ms_pInstance); + ms_pInstance = 0; + } + + protected: + static T * ms_pInstance; +}; + +template T * CSingleton::ms_pInstance = NULL; +*/ +#endif diff --git a/src/DumpProto/dump_proto.cpp b/src/DumpProto/dump_proto.cpp new file mode 100644 index 0000000..9c955ba --- /dev/null +++ b/src/DumpProto/dump_proto.cpp @@ -0,0 +1,1186 @@ +//#include "../../libthecore/include/stdafx.h" +//#include "" +//#define __WIN32__ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lzo.h" + +//������exe���� ����鼭 ���� �߰� : ���� �� �� �ֵ��� �Ͽ���. +#include "CsvFile.h" +#include "ItemCSVReader.h" + + +#pragma comment(lib, "lzo2.lib") + + +#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \ + ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +enum EMisc +{ + CHARACTER_NAME_MAX_LEN = 64, + MOB_SKILL_MAX_NUM = 5, +}; + +enum EMobEnchants +{ + MOB_ENCHANT_CURSE, + MOB_ENCHANT_SLOW, + MOB_ENCHANT_POISON, + MOB_ENCHANT_STUN, + MOB_ENCHANT_CRITICAL, + MOB_ENCHANT_PENETRATE, + MOB_ENCHANTS_MAX_NUM +}; + +enum EMobResists +{ + MOB_RESIST_SWORD, + MOB_RESIST_TWOHAND, + MOB_RESIST_DAGGER, + MOB_RESIST_BELL, + MOB_RESIST_FAN, + MOB_RESIST_BOW, + MOB_RESIST_FIRE, + MOB_RESIST_ELECT, + MOB_RESIST_MAGIC, + MOB_RESIST_WIND, + MOB_RESIST_POISON, + MOB_RESISTS_MAX_NUM +}; + + +#pragma pack(1) +typedef struct SMobSkillLevel +{ + DWORD dwVnum; + BYTE bLevel; +} TMobSkillLevel; +#pragma pack() + +#pragma pack(1) +typedef struct SMobTable +{ + DWORD dwVnum; + char szName[CHARACTER_NAME_MAX_LEN + 1]; + char szLocaleName[CHARACTER_NAME_MAX_LEN + 1]; + + BYTE bType; // Monster, NPC + BYTE bRank; // PAWN, KNIGHT, KING + BYTE bBattleType; // MELEE, etc.. + BYTE bLevel; // Level + BYTE bSize; + + DWORD dwGoldMin; + DWORD dwGoldMax; + DWORD dwExp; + DWORD dwMaxHP; + BYTE bRegenCycle; + BYTE bRegenPercent; + WORD wDef; + + DWORD dwAIFlag; + DWORD dwRaceFlag; + DWORD dwImmuneFlag; + + BYTE bStr, bDex, bCon, bInt; + DWORD dwDamageRange[2]; + + short sAttackSpeed; + short sMovingSpeed; + BYTE bAggresiveHPPct; + WORD wAggressiveSight; + WORD wAttackRange; + + char cEnchants[MOB_ENCHANTS_MAX_NUM]; + char cResists[MOB_RESISTS_MAX_NUM]; + + DWORD dwResurrectionVnum; + DWORD dwDropItemVnum; + + BYTE bMountCapacity; + BYTE bOnClickType; + + BYTE bEmpire; + char szFolder[64 + 1]; + + float fDamMultiply; + + DWORD dwSummonVnum; + DWORD dwDrainSP; + DWORD dwMobColor; + DWORD dwPolymorphItemVnum; + + TMobSkillLevel Skills[MOB_SKILL_MAX_NUM]; + + BYTE bBerserkPoint; + BYTE bStoneSkinPoint; + BYTE bGodSpeedPoint; + BYTE bDeathBlowPoint; + BYTE bRevivePoint; +} TMobTable; +#pragma pack() + + +using namespace std; + +TMobTable * m_pMobTable = NULL; +int m_iMobTableSize = 0; + + +enum EItemMisc +{ + ITEM_NAME_MAX_LEN = 64, + ITEM_VALUES_MAX_NUM = 6, + ITEM_SMALL_DESCR_MAX_LEN = 256, + ITEM_LIMIT_MAX_NUM = 2, + ITEM_APPLY_MAX_NUM = 3, + ITEM_SOCKET_MAX_NUM = 3, + ITEM_MAX_COUNT = 200, + ITEM_ATTRIBUTE_MAX_NUM = 7, + ITEM_ATTRIBUTE_MAX_LEVEL = 5, + ITEM_AWARD_WHY_MAX_LEN = 50, + + REFINE_MATERIAL_MAX_NUM = 5, + + ITEM_ELK_VNUM = 50026, +}; +#pragma pack(1) +typedef struct SItemLimit +{ + BYTE bType; + long lValue; +} TItemLimit; +#pragma pack() + +#pragma pack(1) +typedef struct SItemApply +{ + BYTE bType; + long lValue; +} TItemApply; +#pragma pack() + +#pragma pack(1) +typedef struct +{ + DWORD dwVnum; + DWORD dwVnumRange; + char szName[ITEM_NAME_MAX_LEN + 1]; + char szLocaleName[ITEM_NAME_MAX_LEN + 1]; + BYTE bType; + BYTE bSubType; + + BYTE bWeight; + BYTE bSize; + + DWORD dwAntiFlags; + DWORD dwFlags; + DWORD dwWearFlags; + DWORD dwImmuneFlag; + + DWORD dwGold; + DWORD dwShopBuyPrice; + + TItemLimit aLimits[ITEM_LIMIT_MAX_NUM]; + TItemApply aApplies[ITEM_APPLY_MAX_NUM]; + long alValues[ITEM_VALUES_MAX_NUM]; + long alSockets[ITEM_SOCKET_MAX_NUM]; + DWORD dwRefinedVnum; + WORD wRefineSet; + BYTE bAlterToMagicItemPct; + BYTE bSpecular; + BYTE bGainSocketPct; +} TClientItemTable; +#pragma pack() +bool operator < (const TClientItemTable& lhs, const TClientItemTable& rhs) +{ + return lhs.dwVnum < rhs.dwVnum; +} + +TClientItemTable * m_pItemTable = NULL; +int m_iItemTableSize = 0; + + +bool Set_Proto_Mob_Table(TMobTable *mobTable, cCsvTable &csvTable, std::map &nameMap) +{ + int col = 0; + + mobTable->dwVnum = atoi(csvTable.AsStringByIndex(col++)); + strncpy(mobTable->szName, csvTable.AsStringByIndex(col++), CHARACTER_NAME_MAX_LEN); + //���� ������ �����ϸ� ������ ��. + map::iterator it; + it = nameMap.find(mobTable->dwVnum); + if (it != nameMap.end()) { + const char * localeName = it->second; + strncpy(mobTable->szLocaleName, localeName, sizeof (mobTable->szLocaleName)); + } else { //���� ������ ������, �ѱ��� �״�� ���. + strncpy(mobTable->szLocaleName, mobTable->szName, sizeof (mobTable->szLocaleName)); + } + //4. RANK + int rankValue = get_Mob_Rank_Value(csvTable.AsStringByIndex(col++)); + mobTable->bRank = rankValue; + //5. TYPE + int typeValue = get_Mob_Type_Value(csvTable.AsStringByIndex(col++)); + mobTable->bType = typeValue; + //6. BATTLE_TYPE + int battleTypeValue = get_Mob_BattleType_Value(csvTable.AsStringByIndex(col++)); + mobTable->bBattleType = battleTypeValue; + + mobTable->bLevel = atoi(csvTable.AsStringByIndex(col++)); + //8. SIZE + int sizeValue = get_Mob_Size_Value(csvTable.AsStringByIndex(col++)); + mobTable->bSize = sizeValue; + //9. AI_FLAG + int aiFlagValue = get_Mob_AIFlag_Value(csvTable.AsStringByIndex(col++)); + mobTable->dwAIFlag = aiFlagValue; + col++; //mount_capacity; + //10. RACE_FLAG + int raceFlagValue = get_Mob_RaceFlag_Value(csvTable.AsStringByIndex(col++)); + mobTable->dwRaceFlag = raceFlagValue; + //11. IMMUNE_FLAG + int immuneFlagValue = get_Mob_ImmuneFlag_Value(csvTable.AsStringByIndex(col++)); + mobTable->dwImmuneFlag = immuneFlagValue; + + mobTable->bEmpire = atoi(csvTable.AsStringByIndex(col++)); + + //folder + strncpy(mobTable->szFolder, csvTable.AsStringByIndex(col++), sizeof(mobTable->szFolder)); + + + mobTable->bOnClickType = atoi(csvTable.AsStringByIndex(col++)); + + mobTable->bStr = atoi(csvTable.AsStringByIndex(col++)); + mobTable->bDex = atoi(csvTable.AsStringByIndex(col++)); + mobTable->bCon = atoi(csvTable.AsStringByIndex(col++)); + mobTable->bInt = atoi(csvTable.AsStringByIndex(col++)); + mobTable->dwDamageRange[0] = atoi(csvTable.AsStringByIndex(col++)); + mobTable->dwDamageRange[1] = atoi(csvTable.AsStringByIndex(col++)); + mobTable->dwMaxHP = atoi(csvTable.AsStringByIndex(col++)); + mobTable->bRegenCycle = atoi(csvTable.AsStringByIndex(col++)); + mobTable->bRegenPercent = atoi(csvTable.AsStringByIndex(col++)); + + col++; //gold min + col++; //gold max + mobTable->dwExp = atoi(csvTable.AsStringByIndex(col++)); + mobTable->wDef = atoi(csvTable.AsStringByIndex(col++)); + mobTable->sAttackSpeed = atoi(csvTable.AsStringByIndex(col++)); + mobTable->sMovingSpeed = atoi(csvTable.AsStringByIndex(col++)); + mobTable->bAggresiveHPPct = atoi(csvTable.AsStringByIndex(col++)); + mobTable->wAggressiveSight = atoi(csvTable.AsStringByIndex(col++)); + mobTable->wAttackRange = atoi(csvTable.AsStringByIndex(col++)); + + mobTable->dwDropItemVnum = atoi(csvTable.AsStringByIndex(col++)); + col++; //resurrectionVnum + + + for (int i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i) + mobTable->cEnchants[i] = atoi(csvTable.AsStringByIndex(col++)); + + for (int i = 0; i < MOB_RESISTS_MAX_NUM; ++i) + mobTable->cResists[i] = atoi(csvTable.AsStringByIndex(col++)); + + mobTable->fDamMultiply = atoi(csvTable.AsStringByIndex(col++)); + mobTable->dwSummonVnum = atoi(csvTable.AsStringByIndex(col++)); + mobTable->dwDrainSP = atoi(csvTable.AsStringByIndex(col++)); + mobTable->dwMobColor = atoi(csvTable.AsStringByIndex(col++)); + + return true; +} +bool BuildMobTable(const char* nameFile) +{ + + fprintf(stderr, "sizeof(TMobTable): %u\n", sizeof(TMobTable)); + + + //==============================================================// + //======local�� ���� �̸��� �����ϰ� �ִ� [��] vnum:name======// + //==============================================================// + bool isNameFile = true; + map localMap; + cCsvTable nameData; + if(!nameData.Load(nameFile,'\t')) + { + fprintf(stderr, "%s ������ ���� ���߽��ϴ�\n", nameFile); + isNameFile = false; + } else { + nameData.Next(); + while(nameData.Next()) { + localMap[atoi(nameData.AsStringByIndex(0))] = nameData.AsStringByIndex(1); + } + } + //______________________________________________________________// + + //=========================================// + //======���͵��� vnum�� ������ [��]======// + // *�׽�Ʈ�� ������ ���� �о�ö�, // + // 1. ������ �ִ� ���������� Ȯ���Ҷ� ���// + //=========================================// + set vnumSet; + //_________________________________________// + + //==================================================// + // 2)'mob_proto_test.txt' ������ �о, + // test_mob_table �� �����, + // vnum:TMobTable ���� �����. + //==================================================// + map test_map_mobTableByVnum; + + //1. ���� ����. + cCsvTable test_data; + if(!test_data.Load("mob_proto_test.txt",'\t')) + { + fprintf(stderr, "mob_proto_test.txt ������ ���� ���߽��ϴ�\n"); + //return false; + } else { + test_data.Next(); //���� �ο� �Ѿ��. + + //2. �׽�Ʈ ���� ���̺� ����. + TMobTable * test_mob_table = NULL; + int test_MobTableSize = test_data.m_File.GetRowCount()-1; + test_mob_table = new TMobTable[test_MobTableSize]; + memset(test_mob_table, 0, sizeof(TMobTable) * test_MobTableSize); + + //3. �׽�Ʈ ���� ���̺��� ���� �ְ�, �ʿ����� �ֱ�. + while(test_data.Next()) { + + if (!Set_Proto_Mob_Table(test_mob_table, test_data, localMap)) + { + fprintf(stderr, "�� ������ ���̺� ���� ����.\n"); + } + + + test_map_mobTableByVnum.insert(std::map::value_type(test_mob_table->dwVnum, test_mob_table)); + ++test_mob_table; + } + } + + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// + + + //���� ����. + cCsvTable data; + if(!data.Load("mob_proto.txt",'\t')) + { + fprintf(stderr, "mob_proto.txt ������ ���� ���߽��ϴ�\n"); + return false; + } + data.Next(); //�� ���� ���� (������ Į���� �����ϴ� �κ�) + + + + //===== �� ���̺� ����=====// + if (m_pMobTable) + { + delete m_pMobTable; + m_pMobTable = NULL; + } + + //���� �߰��Ǵ� ������ �ľ��Ѵ�. + int addNumber = 0; + while(data.Next()) { + int vnum = atoi(data.AsStringByIndex(0)); + std::map::iterator it_map_mobTable; + it_map_mobTable = test_map_mobTableByVnum.find(vnum); + if(it_map_mobTable != test_map_mobTableByVnum.end()) { + addNumber++; + } + } + + + m_iMobTableSize = data.m_File.GetRowCount()-1 + addNumber; + + m_pMobTable = new TMobTable[m_iMobTableSize]; + memset(m_pMobTable, 0, sizeof(TMobTable) * m_iMobTableSize); + + TMobTable * mob_table = m_pMobTable; + + + //data�� �ٽ� ù�ٷ� �ű��.(�ٽ� �о�´�;;) + data.Destroy(); + if(!data.Load("mob_proto.txt",'\t')) + { + fprintf(stderr, "mob_proto.txt ������ ���� ���߽��ϴ�\n"); + return false; + } + data.Next(); //�� ���� ���� (������ Į���� �����ϴ� �κ�) + + while (data.Next()) + { + int col = 0; + //�׽�Ʈ ���Ͽ� ���� vnum�� �ִ��� ����. + std::map::iterator it_map_mobTable; + it_map_mobTable = test_map_mobTableByVnum.find(atoi(data.AsStringByIndex(col))); + if(it_map_mobTable == test_map_mobTableByVnum.end()) { + + if (!Set_Proto_Mob_Table(mob_table, data, localMap)) + { + fprintf(stderr, "�� ������ ���̺� ���� ����.\n"); + } + + } else { //$$$$$$$$$$$$$$$$$$$$$$$ �׽�Ʈ ���� ������ �ִ�! + TMobTable *tempTable = it_map_mobTable->second; + + mob_table->dwVnum = tempTable->dwVnum; + strncpy(mob_table->szName, tempTable->szName, CHARACTER_NAME_MAX_LEN); + strncpy(mob_table->szLocaleName, tempTable->szLocaleName, CHARACTER_NAME_MAX_LEN); + mob_table->bRank = tempTable->bRank; + mob_table->bType = tempTable->bType; + mob_table->bBattleType = tempTable->bBattleType; + mob_table->bLevel = tempTable->bLevel; + mob_table->bSize = tempTable->bSize; + mob_table->dwAIFlag = tempTable->dwAIFlag; + mob_table->dwRaceFlag = tempTable->dwRaceFlag; + mob_table->dwImmuneFlag = tempTable->dwImmuneFlag; + mob_table->bEmpire = tempTable->bEmpire; + strncpy(mob_table->szFolder, tempTable->szFolder, CHARACTER_NAME_MAX_LEN); + mob_table->bOnClickType = tempTable->bOnClickType; + mob_table->bStr = tempTable->bStr; + mob_table->bDex = tempTable->bDex; + mob_table->bCon = tempTable->bCon; + mob_table->bInt = tempTable->bInt; + mob_table->dwDamageRange[0] = tempTable->dwDamageRange[0]; + mob_table->dwDamageRange[1] = tempTable->dwDamageRange[1]; + mob_table->dwMaxHP = tempTable->dwMaxHP; + mob_table->bRegenCycle = tempTable->bRegenCycle; + mob_table->bRegenPercent = tempTable->bRegenPercent; + mob_table->dwExp = tempTable->dwExp; + mob_table->wDef = tempTable->wDef; + mob_table->sAttackSpeed = tempTable->sAttackSpeed; + mob_table->sMovingSpeed = tempTable->sMovingSpeed; + mob_table->bAggresiveHPPct = tempTable->bAggresiveHPPct; + mob_table->wAggressiveSight = tempTable->wAggressiveSight; + mob_table->wAttackRange = tempTable->wAttackRange; + mob_table->dwDropItemVnum = tempTable->dwDropItemVnum; + for (int i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i) + mob_table->cEnchants[i] = tempTable->cEnchants[i]; + for (int i = 0; i < MOB_RESISTS_MAX_NUM; ++i) + mob_table->cResists[i] = tempTable->cResists[i]; + mob_table->fDamMultiply = tempTable->fDamMultiply; + mob_table->dwSummonVnum = tempTable->dwSummonVnum; + mob_table->dwDrainSP = tempTable->dwDrainSP; + mob_table->dwMobColor = tempTable->dwMobColor; + + } + + fprintf(stdout, "MOB #%-5d %-16s %-16s sight: %u color %u[%s]\n", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->wAggressiveSight, mob_table->dwMobColor, 0); + + //�¿� vnum �߰� + vnumSet.insert(mob_table->dwVnum); + + ++mob_table; + } + + + + //============================// + //===== �׽�Ʈ ���� �߰� =====// + //%%����%% + //%% -> ���ο� ������ �߰��� // + //�ߺ��Ǵ� ������ ������ �߰� // + //============================// + test_data.Destroy(); + if(!test_data.Load("mob_proto_test.txt",'\t')) + { + fprintf(stderr, "mob_proto_test.txt ������ ���� ���߽��ϴ�\n"); + //return false; + } else { + test_data.Next(); //���� �ο� �Ѿ��. + + while (test_data.Next()) //�׽�Ʈ ������ ������ �Ⱦ����,���ο� ���� �߰��Ѵ�. + { + //�ߺ��Ǵ� �κ��̸� �Ѿ��. + set::iterator itVnum; + itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0))); + if (itVnum != vnumSet.end()) { + continue; + } + + + if (!Set_Proto_Mob_Table(mob_table, test_data, localMap)) + { + fprintf(stderr, "�� ������ ���̺� ���� ����.\n"); + } + + fprintf(stdout, "[New]MOB #%-5d %-16s sight: %u color %u[%s]\n", mob_table->dwVnum, mob_table->szLocaleName, mob_table->wAggressiveSight, mob_table->dwMobColor, test_data.AsStringByIndex(54)); + + //�¿� vnum �߰� + vnumSet.insert(mob_table->dwVnum); + + ++mob_table; + } + } + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// + + printf("BuildMobTable returning TRUE, m_iMobTableSize=%d\n", m_iMobTableSize); + fflush(stdout); + + return true; +} + +bool BuildMobTable() +{ + return BuildMobTable("mob_names.txt"); +} + + + + +DWORD g_adwMobProtoKey[4] = +{ + 4813894, + 18955, + 552631, + 6822045 +}; + + +struct SLocaleFile +{ + std::string locale; + std::string filename; +}; + +static std::vector CollectLocaleFiles(const char* pattern, const char* baseFile, const char* prefix) +{ + std::vector locales; + + _finddata_t data; + intptr_t handle = _findfirst(pattern, &data); + if (handle == -1) + return locales; + + const size_t prefixLen = std::strlen(prefix); + do + { + std::string name = data.name; + if (name == baseFile) + continue; + + size_t underscore = name.find(prefix); + size_t dot = name.rfind('.'); + if (underscore == std::string::npos || dot == std::string::npos || dot <= underscore + prefixLen) + continue; + + std::string locale = name.substr(underscore + prefixLen, dot - (underscore + prefixLen)); + if (!locale.empty()) + locales.push_back({ locale, name }); + } while (_findnext(handle, &data) == 0); + + _findclose(handle); + return locales; +} + +static void EnsureLocaleDirectory(const std::string& locale) +{ + // Create structure: locale/cz instead of locale_cz/locale/cz + std::string root = "locale"; + _mkdir(root.c_str()); + std::string leaf = root + "/" + locale; + _mkdir(leaf.c_str()); +} + +void SaveMobProto(const char* outputPath) +{ + FILE * fp; + + fp = fopen(outputPath, "wb"); + + if (!fp) + { + printf("cannot open %s for writing\n", outputPath); + return; + } + + DWORD fourcc = MAKEFOURCC('M', 'M', 'P', 'T'); + fwrite(&fourcc, sizeof(DWORD), 1, fp); + + DWORD dwElements = m_iMobTableSize; + fwrite(&dwElements, sizeof(DWORD), 1, fp); + + CLZObject zObj; + + printf("sizeof(TMobTable) %d\n", sizeof(TMobTable)); + + if (!CLZO::instance().CompressEncryptedMemory(zObj, m_pMobTable, sizeof(TMobTable) * m_iMobTableSize, g_adwMobProtoKey)) + { + printf("cannot compress\n"); + fclose(fp); + return; + } + + const CLZObject::THeader & r = zObj.GetHeader(); + + printf("MobProto count %u\n%u --Compress--> %u --Encrypt--> %u, GetSize %u\n", + m_iMobTableSize, r.dwRealSize, r.dwCompressedSize, r.dwEncryptSize, zObj.GetSize()); + + DWORD dwDataSize = zObj.GetSize(); + fwrite(&dwDataSize, sizeof(DWORD), 1, fp); + fwrite(zObj.GetBuffer(), dwDataSize, 1, fp); + + fclose(fp); +} + +void SaveMobProto() +{ + SaveMobProto("mob_proto"); +} + +void LoadMobProto() +{ + FILE * fp; + DWORD fourcc, tableSize, dataSize; + + fp = fopen("mob_proto", "rb"); + + fread(&fourcc, sizeof(DWORD), 1, fp); + fread(&tableSize, sizeof(DWORD), 1, fp); + fread(&dataSize, sizeof(DWORD), 1, fp); + BYTE * data = (BYTE *) malloc(dataSize); + + if (data) + { + fread(data, dataSize, 1, fp); + + CLZObject zObj; + + if (CLZO::instance().Decompress(zObj, data, g_adwMobProtoKey)) + { + printf("real_size %u\n", zObj.GetSize()); + + for (DWORD i = 0; i < tableSize; ++i) + { + TMobTable & rTable = *((TMobTable *) zObj.GetBuffer() + i); + printf("%u %s\n", rTable.dwVnum, rTable.szName); + } + } + + free(data); + } + + fclose(fp); +} + + + + +//== ==// +//== ==// +//== ==// +//===== ���⿡������ ������ =====// +//== ==// +//== ==// +//== ==// + +bool Set_Proto_Item_Table(TClientItemTable *itemTable, cCsvTable &csvTable, std::map &nameMap) +{ + // vnum �� vnum range �б�. + { + std::string s(csvTable.AsStringByIndex(0)); + int pos = s.find("~"); + // vnum �ʵ忡 '~'�� ���ٸ� �н� + if (std::string::npos == pos) + { + itemTable->dwVnum = atoi(s.c_str()); + if (0 == itemTable->dwVnum) + { + printf ("INVALID VNUM %s\n", s.c_str()); + return false; + } + itemTable->dwVnumRange = 0; + } + else + { + std::string s_start_vnum (s.substr(0, pos)); + std::string s_end_vnum (s.substr(pos +1 )); + + int start_vnum = atoi(s_start_vnum.c_str()); + int end_vnum = atoi(s_end_vnum.c_str()); + if (0 == start_vnum || (0 != end_vnum && end_vnum < start_vnum)) + { + printf ("INVALID VNUM RANGE%s\n", s.c_str()); + return false; + } + itemTable->dwVnum = start_vnum; + itemTable->dwVnumRange = end_vnum - start_vnum; + } + } + + int col = 1; + + strncpy(itemTable->szName, csvTable.AsStringByIndex(col++), ITEM_NAME_MAX_LEN); + //���� ������ �����ϸ� ������ ��. + map::iterator it; + it = nameMap.find(itemTable->dwVnum); + if (it != nameMap.end()) { + const char * localeName = it->second; + strncpy(itemTable->szLocaleName, localeName, sizeof(itemTable->szLocaleName)); + } else { //���� ������ �������� ������ �ѱ۷�.. + strncpy(itemTable->szLocaleName, itemTable->szName, sizeof(itemTable->szLocaleName)); + } + itemTable->bType = get_Item_Type_Value(csvTable.AsStringByIndex(col++)); + itemTable->bSubType = get_Item_SubType_Value(itemTable->bType, csvTable.AsStringByIndex(col++)); + itemTable->bSize = atoi(csvTable.AsStringByIndex(col++)); + itemTable->dwAntiFlags = get_Item_AntiFlag_Value(csvTable.AsStringByIndex(col++)); + itemTable->dwFlags = get_Item_Flag_Value(csvTable.AsStringByIndex(col++)); + itemTable->dwWearFlags = get_Item_WearFlag_Value(csvTable.AsStringByIndex(col++)); + itemTable->dwImmuneFlag = get_Item_Immune_Value(csvTable.AsStringByIndex(col++)); + itemTable->dwGold = atoi(csvTable.AsStringByIndex(col++)); + itemTable->dwShopBuyPrice = atoi(csvTable.AsStringByIndex(col++)); + itemTable->dwRefinedVnum = atoi(csvTable.AsStringByIndex(col++)); + itemTable->wRefineSet = atoi(csvTable.AsStringByIndex(col++)); + itemTable->bAlterToMagicItemPct = atoi(csvTable.AsStringByIndex(col++)); + + int i; + + for (i = 0; i < ITEM_LIMIT_MAX_NUM; ++i) + { + itemTable->aLimits[i].bType = get_Item_LimitType_Value(csvTable.AsStringByIndex(col++)); + itemTable->aLimits[i].lValue = atoi(csvTable.AsStringByIndex(col++)); + } + + for (i = 0; i < ITEM_APPLY_MAX_NUM; ++i) + { + itemTable->aApplies[i].bType = get_Item_ApplyType_Value(csvTable.AsStringByIndex(col++)); + itemTable->aApplies[i].lValue = atoi(csvTable.AsStringByIndex(col++)); + } + + for (i = 0; i < ITEM_VALUES_MAX_NUM; ++i) + itemTable->alValues[i] = atoi(csvTable.AsStringByIndex(col++)); + + itemTable->bSpecular = atoi(csvTable.AsStringByIndex(col++)); + itemTable->bGainSocketPct = atoi(csvTable.AsStringByIndex(col++)); + col++; //AddonType + + itemTable->bWeight = 0; + + return true; +} + +bool BuildItemTable(const char* nameFile) +{ + //%%% <�Լ� ����> %%%// + //1. ��� : 'item_proto.txt', 'item_proto_test.txt', 'item_names.txt' ������ �а�, + // m_pItemTable �� �����Ѵ�. + //2. ���� + // 1)'item_names.txt' ������ �о vnum:name ���� �����. + // 2)'item_proto_test.txt' ������ �о, + // test_item_table �� �����, + // vnum:TClientItemTable ���� �����. + // 3)'item_proto.txt' ������ �а�, m_pItemTable�� �����Ѵ�. + // test_item_table�� �ִ� vnum�� �׽�Ʈ �����͸� �ִ´�. + // 4)test_item_table �������߿�, m_pItemTable �� ���� �����͸� �߰��Ѵ�. + //3. �׽�Ʈ + // 1)'item_proto.txt' ������ m_pItemTable�� �� ������. + // 2)'item_names.txt' ������ m_pItemTable�� �� ������. + // 3)'item_proto_test.txt' ���� [��ġ��] ������ m_pItemTable �� �� ������. + // 4)'item_proto_test.txt' ���� [���ο�] ������ m_pItemTable �� �� ������. + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// + + fprintf(stderr, "sizeof(TClientItemTable): %u\n", sizeof(TClientItemTable)); + + //=================================================================// + // 1)'item_names.txt' ������ �о vnum:name ���� �����. + //=================================================================// + bool isNameFile = true; + map localMap; + cCsvTable nameData; + if(!nameData.Load(nameFile,'\t')) + { + fprintf(stderr, "%s ������ ���� ���߽��ϴ�\n", nameFile); + isNameFile = false; + } else { + nameData.Next(); + while(nameData.Next()) { + localMap[atoi(nameData.AsStringByIndex(0))] = nameData.AsStringByIndex(1); + } + } + //_________________________________________________________________// + + //===================== =======================// + // 2)'item_proto_test.txt' ������ �о, + // test_item_table �� �����, + // vnum:TClientItemTable ���� �����. + //=============================================// + map test_map_itemTableByVnum; + + //1. ���� ����. + cCsvTable test_data; + if(!test_data.Load("item_proto_test.txt",'\t')) + { + fprintf(stderr, "item_proto_test.txt ������ ���� ���߽��ϴ�\n"); + //return false; + } else { + test_data.Next(); //���� �ο� �Ѿ��. + + //2. �׽�Ʈ ������ ���̺� ����. + TClientItemTable * test_item_table = NULL; + int test_itemTableSize = test_data.m_File.GetRowCount()-1; + test_item_table = new TClientItemTable[test_itemTableSize]; + memset(test_item_table, 0, sizeof(TClientItemTable) * test_itemTableSize); + + //3. �׽�Ʈ ���� ���̺��� ���� �ְ�, �ʿ����� �ֱ�. + while(test_data.Next()) { + + if (!Set_Proto_Item_Table(test_item_table, test_data, localMap)) + { + fprintf(stderr, "�� ������ ���̺� ���� ����.\n"); + } + + + test_map_itemTableByVnum.insert(std::map::value_type(test_item_table->dwVnum, test_item_table)); + ++test_item_table; + } + } + + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// + + + //================================================================// + // 3)'item_proto.txt' ������ �а�, m_pItemTable�� �����Ѵ�. + // test_item_table�� �ִ� vnum�� �׽�Ʈ �����͸� �ִ´�. + //================================================================// + + //vnum���� ������ ��. ���ο� �׽�Ʈ �������� �Ǻ��Ҷ� ���ȴ�. + set vnumSet; + + //���� ����. + cCsvTable data; + if(!data.Load("item_proto.txt",'\t')) + { + fprintf(stderr, "item_proto.txt ������ ���� ���߽��ϴ�\n"); + return false; + } + data.Next(); //�� ���� ���� (������ Į���� �����ϴ� �κ�) + + if (m_pItemTable) + { + free(m_pItemTable); + m_pItemTable = NULL; + } + + //===== ������ ���̺� ���� =====// + //���� �߰��Ǵ� ������ �ľ��Ѵ�. + int addNumber = 0; + while(data.Next()) { + int vnum = atoi(data.AsStringByIndex(0)); + std::map::iterator it_map_itemTable; + it_map_itemTable = test_map_itemTableByVnum.find(vnum); + if(it_map_itemTable != test_map_itemTableByVnum.end()) { + addNumber++; + } + } + //data�� �ٽ� ù�ٷ� �ű��.(�ٽ� �о�´�;;) + data.Destroy(); + if(!data.Load("item_proto.txt",'\t')) + { + fprintf(stderr, "item_proto.txt ������ ���� ���߽��ϴ�\n"); + return false; + } + data.Next(); //�� ���� ���� (������ Į���� �����ϴ� �κ�) + + m_iItemTableSize = data.m_File.GetRowCount()-1+addNumber; + m_pItemTable = new TClientItemTable[m_iItemTableSize]; + memset(m_pItemTable, 0, sizeof(TClientItemTable) * m_iItemTableSize); + + TClientItemTable * item_table = m_pItemTable; + + while (data.Next()) + { + int col = 0; + + //�׽�Ʈ ���Ͽ� ���� vnum�� �ִ��� ����. + std::map::iterator it_map_itemTable; + it_map_itemTable = test_map_itemTableByVnum.find(atoi(data.AsStringByIndex(col))); + if(it_map_itemTable == test_map_itemTableByVnum.end()) { + + + if (!Set_Proto_Item_Table(item_table, data, localMap)) + { + fprintf(stderr, "�� ������ ���̺� ���� ����.\n"); + } + } else { //$$$$$$$$$$$$$$$$$$$$$$$ �׽�Ʈ ������ ������ �ִ�! + TClientItemTable *tempTable = it_map_itemTable->second; + + item_table->dwVnum = tempTable->dwVnum; + strncpy(item_table->szName, tempTable->szName, ITEM_NAME_MAX_LEN); + strncpy(item_table->szLocaleName, tempTable->szLocaleName, ITEM_NAME_MAX_LEN); + item_table->bType = tempTable->bType; + item_table->bSubType = tempTable->bSubType; + item_table->bSize = tempTable->bSize; + item_table->dwAntiFlags = tempTable->dwAntiFlags; + item_table->dwFlags = tempTable->dwFlags; + item_table->dwWearFlags = tempTable->dwWearFlags; + item_table->dwImmuneFlag = tempTable->dwImmuneFlag; + item_table->dwGold = tempTable->dwGold; + item_table->dwShopBuyPrice = tempTable->dwShopBuyPrice; + item_table->dwRefinedVnum = tempTable->dwRefinedVnum; + item_table->wRefineSet = tempTable->wRefineSet; + item_table->bAlterToMagicItemPct = tempTable->bAlterToMagicItemPct; + + int i; + for (i = 0; i < ITEM_LIMIT_MAX_NUM; ++i) + { + item_table->aLimits[i].bType = tempTable->aLimits[i].bType; + item_table->aLimits[i].lValue = tempTable->aLimits[i].lValue; + } + + for (i = 0; i < ITEM_APPLY_MAX_NUM; ++i) + { + item_table->aApplies[i].bType = tempTable->aApplies[i].bType; + item_table->aApplies[i].lValue = tempTable->aApplies[i].lValue; + } + + for (i = 0; i < ITEM_VALUES_MAX_NUM; ++i) + item_table->alValues[i] = tempTable->alValues[i]; + + item_table->bSpecular = tempTable->bSpecular; + item_table->bGainSocketPct = tempTable->bGainSocketPct; + + item_table->bWeight = tempTable->bWeight; + + } + + + fprintf(stdout, "ITEM #%-5u %-24s %-24s VAL: %ld %ld %ld %ld %ld %ld WEAR %u ANTI %u IMMUNE %u REFINE %u\n", + item_table->dwVnum, + item_table->szName, + item_table->szLocaleName, + item_table->alValues[0], + item_table->alValues[1], + item_table->alValues[2], + item_table->alValues[3], + item_table->alValues[4], + item_table->alValues[5], + item_table->dwWearFlags, + item_table->dwAntiFlags, + item_table->dwImmuneFlag, + item_table->dwRefinedVnum); + + //vnum ����. + vnumSet.insert(item_table->dwVnum); + ++item_table; + } + + //==========================================================================// + // 4)test_item_table �������߿�, m_pItemTable �� ���� �����͸� �߰��Ѵ�. + //==========================================================================// + test_data.Destroy(); + if(!test_data.Load("item_proto_test.txt",'\t')) + { + fprintf(stderr, "item_proto_test.txt ������ ���� ���߽��ϴ�\n"); + //return false; + } else { + test_data.Next(); //���� �ο� �Ѿ��. + + while (test_data.Next()) //�׽�Ʈ ������ ������ �Ⱦ����,���ο� ���� �߰��Ѵ�. + { + //�ߺ��Ǵ� �κ��̸� �Ѿ��. + set::iterator itVnum; + itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0))); + if (itVnum != vnumSet.end()) { + continue; + } + + if (!Set_Proto_Item_Table(item_table, test_data, localMap)) + { + fprintf(stderr, "�� ������ ���̺� ���� ����.\n"); + } + + fprintf(stdout, "[NEW]ITEM #%-5u %-24s %-24s VAL: %ld %ld %ld %ld %ld %ld WEAR %u ANTI %u IMMUNE %u REFINE %u\n", + item_table->dwVnum, + item_table->szName, + item_table->szLocaleName, + item_table->alValues[0], + item_table->alValues[1], + item_table->alValues[2], + item_table->alValues[3], + item_table->alValues[4], + item_table->alValues[5], + item_table->dwWearFlags, + item_table->dwAntiFlags, + item_table->dwImmuneFlag, + item_table->dwRefinedVnum); + + + //�¿� vnum �߰� + vnumSet.insert(item_table->dwVnum); + + ++item_table; + + } + } + + return true; +} + +bool BuildItemTable() +{ + return BuildItemTable("item_names.txt"); +} + +DWORD g_adwItemProtoKey[4] = +{ + 173217, + 72619434, + 408587239, + 27973291 +}; + +void SaveItemProto(const char* outputPath) +{ + FILE * fp; + + fp = fopen(outputPath, "wb"); + + if (!fp) + { + printf("cannot open %s for writing\n", outputPath); + return; + } + + DWORD fourcc = MAKEFOURCC('M', 'I', 'P', 'X'); + fwrite(&fourcc, sizeof(DWORD), 1, fp); + + DWORD dwVersion = 0x00000001; + fwrite(&dwVersion, sizeof(DWORD), 1, fp); + + DWORD dwStride = sizeof(TClientItemTable); + fwrite(&dwStride, sizeof(DWORD), 1, fp); + + DWORD dwElements = m_iItemTableSize; + fwrite(&dwElements, sizeof(DWORD), 1, fp); + + CLZObject zObj; + std::vector vec_item_table (&m_pItemTable[0], &m_pItemTable[m_iItemTableSize - 1]); + sort (&m_pItemTable[0], &m_pItemTable[0] + m_iItemTableSize); + if (!CLZO::instance().CompressEncryptedMemory(zObj, m_pItemTable, sizeof(TClientItemTable) * m_iItemTableSize, g_adwItemProtoKey)) + { + printf("cannot compress\n"); + fclose(fp); + return; + } + + const CLZObject::THeader & r = zObj.GetHeader(); + + printf("Elements %d\n%u --Compress--> %u --Encrypt--> %u, GetSize %u\n", + m_iItemTableSize, + r.dwRealSize, + r.dwCompressedSize, + r.dwEncryptSize, + zObj.GetSize()); + + DWORD dwDataSize = zObj.GetSize(); + fwrite(&dwDataSize, sizeof(DWORD), 1, fp); + fwrite(zObj.GetBuffer(), dwDataSize, 1, fp); + + fclose(fp); + + fp = fopen(outputPath, "rb"); + + if (!fp) + { + printf("Error!!\n"); + return; + } + + fread(&fourcc, sizeof(DWORD), 1, fp); + fread(&dwElements, sizeof(DWORD), 1, fp); + + printf("Elements Check %u fourcc match %d\n", dwElements, fourcc == MAKEFOURCC('M', 'I', 'P', 'T')); + fclose(fp); +} + +void SaveItemProto() +{ + SaveItemProto("item_proto"); +} + +static void BuildLocalizedMobProtos() +{ + const std::vector locales = CollectLocaleFiles("mob_names_*.txt", "mob_names.txt", "mob_names_"); + for (const SLocaleFile& locale : locales) + { + EnsureLocaleDirectory(locale.locale); + std::string output = std::string("locale/") + locale.locale + "/mob_proto"; + if (BuildMobTable(locale.filename.c_str())) + { + SaveMobProto(output.c_str()); + } + else + { + fprintf(stderr, "Skipping locale %s because mob table build failed.\n", locale.locale.c_str()); + } + } +} + +static void BuildLocalizedItemProtos() +{ + const std::vector locales = CollectLocaleFiles("item_names_*.txt", "item_names.txt", "item_names_"); + for (const SLocaleFile& locale : locales) + { + EnsureLocaleDirectory(locale.locale); + std::string output = std::string("locale/") + locale.locale + "/item_proto"; + if (BuildItemTable(locale.filename.c_str())) + { + SaveItemProto(output.c_str()); + } + else + { + fprintf(stderr, "Skipping locale %s because item table build failed.\n", locale.locale.c_str()); + } + } +} + + + +int main(int argc, char ** argv) +{ + + printf("=== MAIN START ===\n"); + fflush(stdout); + + if (BuildMobTable()) + { + printf("=== BuildMobTable returned TRUE ===\n"); + fflush(stdout); + printf("=== About to call SaveMobProto ===\n"); + fflush(stdout); + SaveMobProto(); + printf("=== SaveMobProto returned ===\n"); + fflush(stdout); + LoadMobProto(); + cout << "BuildMobTable working normal" << endl; + BuildLocalizedMobProtos(); + } else { + printf("=== BuildMobTable returned FALSE ===\n"); + fflush(stdout); + } + + + + if (BuildItemTable()) + { + SaveItemProto(); + BuildLocalizedItemProtos(); + cout << "BuildItemTable working normal" << endl; + } + + + + return 0; +} + diff --git a/src/DumpProto/lzo.cpp b/src/DumpProto/lzo.cpp new file mode 100644 index 0000000..8fd3b52 --- /dev/null +++ b/src/DumpProto/lzo.cpp @@ -0,0 +1,261 @@ +//#include "common.h" +#include +#include +#include +#include "lzo.h" +#include "tea.h" + +// Global instance of CLZO singleton to initialize the singleton pattern +static CLZO g_lzoInstance; + +#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \ + ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) + +DWORD CLZObject::ms_dwFourCC = MAKEFOURCC('M', 'C', 'O', 'Z'); + +CLZObject::CLZObject() +{ + Initialize(); +} + +void CLZObject::Initialize() +{ + m_pHeader = NULL; + m_pbBuffer = NULL; + m_dwBufferSize = 0; + m_pbIn = NULL; + m_bCompressed = false; +} + +void CLZObject::Clear() +{ + if (m_pbBuffer) + delete [] m_pbBuffer; + + Initialize(); +} + +CLZObject::~CLZObject() +{ + Clear(); +} + +DWORD CLZObject::GetSize() +{ + assert(m_pHeader); + + if (m_bCompressed) + { + if (m_pHeader->dwEncryptSize) + return sizeof(THeader) + sizeof(DWORD) + m_pHeader->dwEncryptSize; + else + return sizeof(THeader) + sizeof(DWORD) + m_pHeader->dwCompressedSize; + } + else + return m_pHeader->dwRealSize; +} + +void CLZObject::BeginCompress(const void * pvIn, UINT uiInLen) +{ + m_pbIn = (const BYTE *) pvIn; + + // sizeof(SHeader) + + // ��ȣȭ�� ���� fourCC 4����Ʈ + // ����� �� ������� �� �ִ� �ִ� �뷮 + + // ��ȣȭ�� ���� 8 ����Ʈ + m_dwBufferSize = sizeof(THeader) + sizeof(DWORD) + (uiInLen + uiInLen / 64 + 16 + 3) + 8; + + m_pbBuffer = new BYTE[m_dwBufferSize]; + memset(m_pbBuffer, 0, m_dwBufferSize); + + m_pHeader = (THeader *) m_pbBuffer; + m_pHeader->dwFourCC = ms_dwFourCC; + m_pHeader->dwEncryptSize = m_pHeader->dwCompressedSize = m_pHeader->dwRealSize = 0; + m_pHeader->dwRealSize = uiInLen; +} + + +bool CLZObject::Compress() +{ + BYTE * pbBuffer = m_pbBuffer + sizeof(THeader); + *(DWORD *) pbBuffer = 0x5A4F434D; // 'MOCZ' + pbBuffer += sizeof(DWORD); + + // Calculate available space for compressed data + lzo_uint available_space = (lzo_uint)(m_dwBufferSize - sizeof(THeader) - sizeof(DWORD)); + lzo_uint compressed_size = available_space; + + int r = lzo1x_1_compress( + (BYTE *) m_pbIn, + (lzo_uint)m_pHeader->dwRealSize, + pbBuffer, + &compressed_size, + CLZO::instance().GetWorkMemory() + ); + + if (LZO_E_OK != r) + { + return false; + } + + m_pHeader->dwCompressedSize = (DWORD)compressed_size; + m_bCompressed = true; + + return true; +} + +bool CLZObject::BeginDecompress(const void * pvIn) +{ + THeader * pHeader = (THeader *) pvIn; + + if (pHeader->dwFourCC != ms_dwFourCC) + { + fprintf(stderr, "LZObject: not a valid data"); + return false; + } + + m_pHeader = pHeader; + m_pbIn = (const BYTE *) pvIn + (sizeof(THeader) + sizeof(DWORD)); + + m_pbBuffer = new BYTE[pHeader->dwRealSize]; + memset(m_pbBuffer, 0, pHeader->dwRealSize); + return true; +} + +bool CLZObject::Decompress(DWORD * pdwKey) +{ + UINT uiSize; + int r; + + if (m_pHeader->dwEncryptSize) + { + BYTE * pbDecryptedBuffer = Decrypt(pdwKey); + + if (*(DWORD *) pbDecryptedBuffer != ms_dwFourCC) + { + fprintf(stderr, "LZObject: key incorrect"); + return false; + } + + if (LZO_E_OK != (r = lzo1x_decompress(pbDecryptedBuffer + sizeof(DWORD), m_pHeader->dwCompressedSize, m_pbBuffer, (lzo_uint*)&uiSize, NULL))) + { + fprintf(stderr, "LZObject: Decompress failed(decrypt) ret %d\n", r); + return false; + } + + delete [] pbDecryptedBuffer; + } + else + { + uiSize = m_pHeader->dwRealSize; + + if (LZO_E_OK != (r = lzo1x_decompress_safe(m_pbIn, m_pHeader->dwCompressedSize, m_pbBuffer, (lzo_uint*)&uiSize, NULL))) + { + fprintf(stderr, "LZObject: Decompress failed : ret %d, CompressedSize %d\n", r, m_pHeader->dwCompressedSize); + return false; + } + } + + if (uiSize != m_pHeader->dwRealSize) + { + fprintf(stderr, "LZObject: Size differs"); + return false; + } + + return true; +} + +bool CLZObject::Encrypt(DWORD * pdwKey) +{ + if (!m_bCompressed) + { + assert(!"not compressed yet"); + return false; + } + + BYTE * pbBuffer = m_pbBuffer + sizeof(THeader); + // TEA pads to 8-byte boundaries; encrypt the FourCC + compressed data + DWORD dwSizeToEncrypt = sizeof(DWORD) + m_pHeader->dwCompressedSize; + fprintf(stderr, "Encrypt: dwCompressedSize=%u, dwSizeToEncrypt=%u\n", m_pHeader->dwCompressedSize, dwSizeToEncrypt); + m_pHeader->dwEncryptSize = tea_encrypt((DWORD *) pbBuffer, (const DWORD *) pbBuffer, pdwKey, dwSizeToEncrypt); + fprintf(stderr, "Encrypt: dwEncryptSize=%u (return from tea_encrypt)\n", m_pHeader->dwEncryptSize); + if (m_pHeader->dwEncryptSize == 0) + { + fprintf(stderr, "Encrypt: tea_encrypt failed (returned 0)\n"); + return false; + } + return true; +} + +BYTE * CLZObject::Decrypt(DWORD * pdwKey) +{ + assert(m_pbBuffer); + + BYTE * pbDecryptBuffer = new BYTE[m_pHeader->dwEncryptSize]; + + tea_encrypt((DWORD *) pbDecryptBuffer, (const DWORD *) (m_pbIn - sizeof(DWORD)), pdwKey, m_pHeader->dwEncryptSize); + return pbDecryptBuffer; +} + +CLZO::CLZO() : m_pWorkMem(NULL) +{ + if (lzo_init() != LZO_E_OK) + { + fprintf(stderr, "LZO: cannot initialize\n"); + return; + } + + m_pWorkMem = (BYTE *) malloc(LZO1X_MEM_COMPRESS); + + if (NULL == m_pWorkMem) + { + fprintf(stderr, "LZO: cannot alloc memory\n"); + return; + } +} + +CLZO::~CLZO() +{ + if (m_pWorkMem) + { + free(m_pWorkMem); + m_pWorkMem = NULL; + } +} + +bool CLZO::CompressMemory(CLZObject & rObj, const void * pIn, UINT uiInLen) +{ + rObj.BeginCompress(pIn, uiInLen); + return rObj.Compress(); +} + +bool CLZO::CompressEncryptedMemory(CLZObject & rObj, const void * pIn, UINT uiInLen, DWORD * pdwKey) +{ + rObj.BeginCompress(pIn, uiInLen); + + if (!rObj.Compress()) + { + return false; + } + + return rObj.Encrypt(pdwKey); +} + +bool CLZO::Decompress(CLZObject & rObj, const BYTE * pbBuf, DWORD * pdwKey) +{ + if (!rObj.BeginDecompress(pbBuf)) + return false; + + if (!rObj.Decompress(pdwKey)) + return false; + + return true; +} + + +BYTE * CLZO::GetWorkMemory() +{ + return m_pWorkMem; +} + diff --git a/src/DumpProto/lzo.h b/src/DumpProto/lzo.h new file mode 100644 index 0000000..2c069c3 --- /dev/null +++ b/src/DumpProto/lzo.h @@ -0,0 +1,70 @@ +#ifndef __INC_METIN_II_371GNFBQOCJ_LZO_H__ +#define __INC_METIN_II_371GNFBQOCJ_LZO_H__ + +#include "Singleton.h" +#include +#include + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef unsigned int UINT; + +class CLZObject { +public: +#pragma pack(4) + typedef struct SHeader { + DWORD dwFourCC; + DWORD dwEncryptSize; // ��ȣȭ�� ũ�� + DWORD dwCompressedSize; // ����� ������ ũ�� + DWORD dwRealSize; // ���� ������ ũ�� + } THeader; +#pragma pack() + + CLZObject(); + ~CLZObject(); + + void Clear(); + + void BeginCompress(const void *pvIn, UINT uiInLen); + bool Compress(); + + bool BeginDecompress(const void *pvIn); + bool Decompress(DWORD *pdwKey = NULL); + + bool Encrypt(DWORD *pdwKey); + BYTE *Decrypt(DWORD *pdwKey); + + const THeader &GetHeader() { return *m_pHeader; } + BYTE *GetBuffer() { return m_pbBuffer; } + DWORD GetSize(); + +private: + void Initialize(); + + BYTE *m_pbBuffer; + DWORD m_dwBufferSize; + + THeader *m_pHeader; + const BYTE *m_pbIn; + bool m_bCompressed; + + static DWORD ms_dwFourCC; +}; + +class CLZO : public singleton { +public: + CLZO(); + virtual ~CLZO(); + + bool CompressMemory(CLZObject &rObj, const void *pIn, UINT uiInLen); + bool CompressEncryptedMemory(CLZObject &rObj, const void *pIn, UINT uiInLen, + DWORD *pdwKey); + bool Decompress(CLZObject &rObj, const BYTE *pbBuf, DWORD *pdwKey = NULL); + BYTE *GetWorkMemory(); + +private: + BYTE *m_pWorkMem; +}; + +#endif diff --git a/src/DumpProto/tea.cpp b/src/DumpProto/tea.cpp new file mode 100644 index 0000000..d8c9899 --- /dev/null +++ b/src/DumpProto/tea.cpp @@ -0,0 +1,100 @@ +/* +* Filename: tea.c +* Description: TEA ¾Ïȣȭ ¸ðµâ +* +* Author: ±èÇÑÁÖ (aka. ºñ¿±, Cronan), ¼Û¿µÁø (aka. myevan, ºøÀÚ·ç) +*/ +#include "tea.h" +#include + +/* +* TEA Encryption Module Instruction +* Edited by ±èÇÑÁÖ aka. ºñ¿±, Cronan +* +* void tea_code(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest) +* void tea_decode(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest) +* 8¹ÙÀÌÆ®¸¦ ¾ÏÈ£/º¹È£È­ ÇÒ¶§ »ç¿ëµÈ´Ù. key ´Â 16 ¹ÙÀÌÆ®¿©¾ß ÇÑ´Ù. +* sz, sy ´Â 8¹ÙÀÌÆ®ÀÇ ¿ª¼øÀ¸·Î ´ëÀÔÇÑ´Ù. +* +* int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size); +* int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size); +* ÇѲ¨¹ø¿¡ 8 ¹ÙÀÌÆ® ÀÌ»óÀ» ¾ÏÈ£/º¹È£È­ ÇÒ¶§ »ç¿ëÇÑ´Ù. ¸¸¾à size °¡ +* 8ÀÇ ¹è¼ö°¡ ¾Æ´Ï¸é 8ÀÇ ¹è¼ö·Î Å©±â¸¦ "´Ã·Á¼­" ¾Ïȣȭ ÇÑ´Ù. +* +* ex. tea_code(pdwSrc[1], pdwSrc[0], pdwKey, pdwDest); +* tea_decrypt(pdwDest, pdwSrc, pdwKey, nSize); +*/ + +#define TEA_ROUND 32 // 32 ¸¦ ±ÇÀåÇϸç, ³ôÀ» ¼ö·Ï °á°ú°¡ ³­ÇØÇØ Áø´Ù. +#define DELTA 0x9E3779B9 // DELTA °ª ¹Ù²ÙÁö ¸»°Í. + +void tea_code(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest) +{ + register unsigned long y = sy, z = sz, sum = 0; + unsigned long n = TEA_ROUND; + + while (n-- > 0) + { + y += ((z << 4 ^ z >> 5) + z) ^ (sum + key[sum & 3]); + sum += DELTA; + z += ((y << 4 ^ y >> 5) + y) ^ (sum + key[sum >> 11 & 3]); + } + + *(dest++) = y; + *dest = z; +} + +void tea_decode(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest) +{ +#pragma warning(disable:4307) + register unsigned long y = sy, z = sz, sum = DELTA * TEA_ROUND; +#pragma warning(default:4307) + + unsigned long n = TEA_ROUND; + + while (n-- > 0) + { + z -= ((y << 4 ^ y >> 5) + y) ^ (sum + key[sum >> 11 & 3]); + sum -= DELTA; + y -= ((z << 4 ^ z >> 5) + z) ^ (sum + key[sum & 3]); + } + + *(dest++) = y; + *dest = z; +} + +int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long * key, int size) +{ + int i; + int resize; + + if (size % 8 != 0) + { + resize = size + 8 - (size % 8); + memset((char *) src + size, 0, resize - size); + } + else + resize = size; + + for (i = 0; i < resize >> 3; i++, dest += 2, src += 2) + tea_code(*(src + 1), *src, key, dest); + + return (resize); +} + +int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long * key, int size) +{ + int i; + int resize; + + if (size % 8 != 0) + resize = size + 8 - (size % 8); + else + resize = size; + + for (i = 0; i < resize >> 3; i++, dest += 2, src += 2) + tea_decode(*(src + 1), *src, key, dest); + + return (resize); +} + diff --git a/src/DumpProto/tea.h b/src/DumpProto/tea.h new file mode 100644 index 0000000..3555bc2 --- /dev/null +++ b/src/DumpProto/tea.h @@ -0,0 +1,17 @@ +#ifdef __cplusplus +extern "C" { +#endif + + /* TEA is a 64-bit symmetric block cipher with a 128-bit key, developed + by David J. Wheeler and Roger M. Needham, and described in their + paper at . + + This implementation is based on their code in + */ + + int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size); + int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size); + +#ifdef __cplusplus +}; +#endif