From 4235742d87fcf4390d4479a50c400bcd1d417b12 Mon Sep 17 00:00:00 2001 From: thejinchao Date: Thu, 4 Sep 2025 14:30:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0List=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libnpk/libNPK.h | 12 +- libnpk/source/libNPK_FileList.cpp | 252 +++++++++++++++++++++++++++++- libnpk/source/libNPK_FileList.h | 22 ++- libnpk/source/libNPK_NPKFile.cpp | 11 +- lua/CMakeLists.txt | 2 +- lua/src/lbit.c | 182 +++++++++++++++++++++ lua/src/linit.c | 1 + lua/src/lualib.h | 2 + sgutil/lua/dump_npk_list.lua | 104 +++++------- sgutil/lua/extrace_npk_file.lua | 7 + sgutil/sgu_lua_npk_file.cpp | 81 +++++++++- sgutil/sgu_lua_npk_file.h | 8 +- sgutil/sgu_mode_run_lua_file.cpp | 13 +- 13 files changed, 615 insertions(+), 82 deletions(-) create mode 100644 lua/src/lbit.c diff --git a/libnpk/libNPK.h b/libnpk/libNPK.h index f8b5858..0fdfc29 100644 --- a/libnpk/libNPK.h +++ b/libnpk/libNPK.h @@ -30,6 +30,7 @@ enum ErrorCode NPK_ERR_INVALID_STATE, NPK_ERR_NEW_FAILED, NPK_ERR_FILE_CREATE, + NPK_ERR_DUPLICATE_KEYNAME, //Other errors NPK_ERR_UNKNOWN }; @@ -105,10 +106,17 @@ public: class IFileList { public: + virtual bool loadListFromFile(const wchar_t* wszListFile, const char* prefix, + bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC, + bool bEnableDuplicate) = 0; + virtual bool dumpToLocalFile(const wchar_t* wszListFile, + bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC) = 0; + virtual bool mergeOtherListInto(const IFileList* sourceFileList, bool bEnableDuplicate) = 0; + virtual bool applyToLocalNPKFiles(const wchar_t* wszNPKBase) = 0; + virtual int32_t getFileCounts(void) const = 0; virtual bool getFileItem(int32_t index, FileItemFullInfo* fileItemFullInfo) const = 0; - virtual void addFileNode(const FileItemFullInfo& fileItemFullInfo) = 0; - virtual void mergeOtherListInto(const IFileList* sourceFileList) = 0; + virtual bool getFileItem(const char* szKeyName, FileItemFullInfo* fileItemFullInfo) const = 0; }; } diff --git a/libnpk/source/libNPK_FileList.cpp b/libnpk/source/libNPK_FileList.cpp index 12bdfff..c6e999e 100644 --- a/libnpk/source/libNPK_FileList.cpp +++ b/libnpk/source/libNPK_FileList.cpp @@ -1,8 +1,142 @@ #include "libNPK_FileList.h" +#include "libNPK_Errors.h" +#include "libNPK_Utils.h" + +#include +#include + +#include +#include +#include +#include namespace NPK { +const char LIST_FILE_SPE_CHAR = '|'; + +void NPKFileList::clear() +{ + m_fileList.clear(); +} + +bool NPKFileList::loadListFromFile(const wchar_t* wszListFile, const char* prefix, + bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC, + bool bEnableDuplicate) +{ + int tokeCounts = 1; + tokeCounts += bNpkBase ? 1 : 0; + tokeCounts += bNpkName ? 1 : 0; + tokeCounts += bFileOffset ? 1 : 0; + tokeCounts += bFileSize ? 1 : 0; + tokeCounts += bFileCRC ? 1 : 0; + + std::ifstream file(wszListFile); + if (!file.is_open()) + { + setLastError(NPK_ERR_FILE_ACCESS); + return false; + } + + size_t prefixLen = (prefix!= nullptr ? strlen(prefix) : 0); + std::string line; + while (std::getline(file, line)) + { + if (line.empty()) continue; + if (prefix != nullptr) + { + if (strncmp(prefix, line.c_str(), prefixLen) != 0) + { + continue; + } + } + + std::stringstream lineSteam(line); + std::vector fileData; + std::string token; + + while (std::getline(lineSteam, token, LIST_FILE_SPE_CHAR)) + { + fileData.push_back(token); + } + + if (fileData.size() != tokeCounts) + { + continue; + } + + FileItemFullInfo fullInfo; + int32_t currentIT = 0; + + //parser key name + fullInfo.keyName = fileData[currentIT++]; + if (bNpkBase) { + fullInfo.npkBase = fileData[currentIT++]; + } + if (bNpkName) { + fullInfo.npkName = fileData[currentIT++]; + } + if (bFileOffset) { + fullInfo.fileOffset = (uint32_t)(_atoi64(fileData[currentIT++].c_str())); + } + if (bFileSize) { + fullInfo.fileSize = (uint32_t)(_atoi64(fileData[currentIT++].c_str())); + } + if (bFileCRC) { + fullInfo.fileCRC = (uint32_t)(_atoi64(fileData[currentIT++].c_str())); + } + if (!addFileNode(fullInfo, bEnableDuplicate)) + { + file.close(); + clear(); + setLastError(NPK_ERR_DUPLICATE_KEYNAME); + return false; + } + } + file.close(); + return true; +} + +bool NPKFileList::dumpToLocalFile(const wchar_t* wszListFile, + bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC) +{ + std::ofstream file(wszListFile); + if (!file.is_open()) + { + setLastError(NPK_ERR_FILE_ACCESS); + return false; + } + + for (size_t i = 0; i < m_fileList.size(); i++) + { + const FileItemFullInfo& fullInfo = m_fileList[i]; + + std::string line = fullInfo.keyName; + if (bNpkBase) + { + line += LIST_FILE_SPE_CHAR + fullInfo.npkBase; + } + if (bNpkName) + { + line += LIST_FILE_SPE_CHAR + fullInfo.npkName; + } + if (bFileOffset) + { + line += LIST_FILE_SPE_CHAR + std::to_string(fullInfo.fileOffset); + } + if (bFileSize) + { + line += LIST_FILE_SPE_CHAR + std::to_string(fullInfo.fileSize); + } + if (bFileCRC) + { + line += LIST_FILE_SPE_CHAR + std::to_string(fullInfo.fileCRC); + } + file << line << std::endl; + } + file.close(); + return true; +} int32_t NPKFileList::getFileCounts(void) const { @@ -19,15 +153,125 @@ bool NPKFileList::getFileItem(int32_t index, FileItemFullInfo* fullInfo) const return true; } -void NPKFileList::addFileNode(const FileItemFullInfo& fullInfo) +bool NPKFileList::getFileItem(const char* szKeyName, FileItemFullInfo* fileItemFullInfo) const { - //TODO: check duplicate file name? - m_fileList.push_back(fullInfo); + auto it = m_hashList.find(szKeyName); + if (it == m_hashList.end()) + { + return false; + } + *fileItemFullInfo = m_fileList[it->second]; + return true; } -void NPKFileList::mergeOtherListInto(const IFileList* source) +bool NPKFileList::addFileNode(const FileItemFullInfo& fullInfo, bool bEnableDuplicate) { + auto currentIT = m_hashList.find(fullInfo.keyName); + //check duplicate file name? + if (currentIT != m_hashList.end()) + { + if (bEnableDuplicate) + { + m_fileList[currentIT->second] = fullInfo; + return true; + } + else + { + return false; + } + } + auto newIT = m_fileList.size(); + m_fileList.push_back(fullInfo); + m_hashList.insert(std::make_pair(fullInfo.keyName, newIT)); + return true; +} + +bool NPKFileList::mergeOtherListInto(const IFileList* source, bool bEnableDuplicate) +{ + if (source == nullptr) + { + setLastError(NPK_ERR_PARAM); + return false; + } + + int32_t counts = source->getFileCounts(); + for (int32_t i = 0; i < counts; i++) + { + FileItemFullInfo fullInfo; + source->getFileItem(i, &fullInfo); + + if (!addFileNode(fullInfo, bEnableDuplicate)) + { + return false; + } + } + return true; +} + +bool NPKFileList::applyToLocalNPKFiles(const wchar_t* wszNPKBase) +{ + if (wszNPKBase == 0 || wszNPKBase[0] == L'\0') + { + setLastError(NPK_ERR_PARAM); + return false; + } + + if (!PathFileExistsW(wszNPKBase) || !PathIsDirectoryW(wszNPKBase)) + { + setLastError(NPK_ERR_FILE_ACCESS); + return false; + } + + bool result = true; + std::map> npkFileMap; + for (size_t i = 0; i < m_fileList.size(); i++) + { + FileItemFullInfo& fullInfo = m_fileList[i]; + + std::wstring strNPKName = getNPKPathNameFromKeyName(wszNPKBase, fullInfo.keyName.c_str()); + auto it = npkFileMap.find(strNPKName); + if (it == npkFileMap.end()) + { + INPKFile* npkFile = NPK::createNPKFile(); + if (!(npkFile->openPakFile(strNPKName.c_str()))) + { + result = false; + setLastError(NPK_ERR_FILE_ACCESS); + break; + } + IFileList* fullList = npkFile->generateFullInfoList(); + npkFileMap.insert(std::make_pair(strNPKName, std::make_pair(npkFile, fullList))); + it = npkFileMap.find(strNPKName); + } + + IFileList* fullList = it->second.second; + fullList->getFileItem(fullInfo.keyName.c_str(), &fullInfo); + } + + for (auto it = npkFileMap.begin(); it != npkFileMap.end(); ++it) + { + destoryFileList(it->second.second); + it->second.first->closePakFile(); + } + npkFileMap.clear(); + return result; +} + +std::wstring NPKFileList::getNPKPathNameFromKeyName(const wchar_t* wszNPKBase, const char* keyName) +{ + std::wstring strKeyName = convertUtf8StringToWide(keyName); + std::string::size_type lastSep = strKeyName.rfind(L'/'); + if (lastSep != std::string::npos) + { + strKeyName = strKeyName.substr(0, lastSep); + } + std::replace(strKeyName.begin(), strKeyName.end(), L'/', L'_'); + wchar_t wszNPKPathName[1024] = { 0 }; + StringCchCopyW(wszNPKPathName, 1024, wszNPKBase); + PathAppendW(wszNPKPathName, strKeyName.c_str()); + PathAddExtensionW(wszNPKPathName, L".NPK"); + return std::wstring(wszNPKPathName); } IFileList* createEmptyFileList() diff --git a/libnpk/source/libNPK_FileList.h b/libnpk/source/libNPK_FileList.h index 543c645..f0faec2 100644 --- a/libnpk/source/libNPK_FileList.h +++ b/libnpk/source/libNPK_FileList.h @@ -2,19 +2,37 @@ #include "libNPK.h" #include +#include namespace NPK { class NPKFileList : public IFileList { public: + +public: + virtual bool loadListFromFile(const wchar_t* wszListFile, const char* prefix, + bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC, + bool bEnableDuplicate) override; + virtual bool dumpToLocalFile(const wchar_t* wszListFile, + bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC); + virtual bool mergeOtherListInto(const IFileList* sourceFileList, bool bEnableDuplicate) override; + virtual bool applyToLocalNPKFiles(const wchar_t* wszNPKBase) override; + virtual int32_t getFileCounts(void) const override; virtual bool getFileItem(int32_t index, FileItemFullInfo* fullInfo) const override; - virtual void addFileNode(const FileItemFullInfo& fullInfo) override; - virtual void mergeOtherListInto(const IFileList* sourceFileList) override; + virtual bool getFileItem(const char* szKeyName, FileItemFullInfo* fileItemFullInfo) const override; + +public: + bool addFileNode(const FileItemFullInfo& fullInfo, bool bEnableDuplicate); + +private: + void clear(); + std::wstring getNPKPathNameFromKeyName(const wchar_t* wszNPKBase, const char* keyName); private: std::vector m_fileList; + std::unordered_map::size_type> m_hashList; }; } diff --git a/libnpk/source/libNPK_NPKFile.cpp b/libnpk/source/libNPK_NPKFile.cpp index 94558e0..aee8431 100644 --- a/libnpk/source/libNPK_NPKFile.cpp +++ b/libnpk/source/libNPK_NPKFile.cpp @@ -4,6 +4,7 @@ #include "libEncrypt_SHA256.h" #include "libNPK_FileStream.h" #include "libNPK_Utils.h" +#include "libNPK_FileList.h" #include @@ -302,7 +303,15 @@ IFileList* CNPKFile::generateFullInfoList(void) { fullInfo.fileCRC = 0; } - pFileList->addFileNode(fullInfo); // Add file item to the list + // Add file item to the list + if (!((NPKFileList*)pFileList)->addFileNode(fullInfo, false)) + { + //duplicate key name, error! + closeFileStream(pFileStream); + destoryFileList(pFileList); + setLastError(NPK_ERR_INVALID_FILE_FORMAT, "Duplicate keyname in NPK file"); + return nullptr; + } } return pFileList; } diff --git a/lua/CMakeLists.txt b/lua/CMakeLists.txt index e3ae0d7..8574b8f 100644 --- a/lua/CMakeLists.txt +++ b/lua/CMakeLists.txt @@ -3,7 +3,7 @@ set(srcDir src) set(srcFiles lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c ldo.c ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c loslib.c lparser.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c ltm.c lundump.c - lvm.c lzio.c) + lvm.c lzio.c lbit.c) set(publicHeaderFiles lauxlib.h lua.h luaconf.h lualib.h) diff --git a/lua/src/lbit.c b/lua/src/lbit.c new file mode 100644 index 0000000..7fd6c54 --- /dev/null +++ b/lua/src/lbit.c @@ -0,0 +1,182 @@ +/* +** Lua BitOp -- a bit operations library for Lua 5.1/5.2. +** http://bitop.luajit.org/ +** +** Copyright (C) 2008-2025 Mike Pall. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] +*/ + +#define LUA_BITOP_VERSION "1.0.3" + +#define LUA_LIB +#include "lua.h" +#include "lauxlib.h" + +#include + +typedef int32_t SBits; +typedef uint32_t UBits; + +typedef union { + lua_Number n; +#ifdef LUA_NUMBER_DOUBLE + uint64_t b; +#else + UBits b; +#endif +} BitNum; + +/* Convert argument to bit type. */ +static UBits barg(lua_State *L, int idx) +{ + BitNum bn; + UBits b; +#if LUA_VERSION_NUM < 502 + bn.n = lua_tonumber(L, idx); +#else + bn.n = luaL_checknumber(L, idx); +#endif +#if defined(LUA_NUMBER_DOUBLE) + bn.n += 6755399441055744.0; /* 2^52+2^51 */ +#ifdef SWAPPED_DOUBLE + b = (UBits)(bn.b >> 32); +#else + b = (UBits)bn.b; +#endif +#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \ + defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \ + defined(LUA_NUMBER_LLONG) + if (sizeof(UBits) == sizeof(lua_Number)) + b = bn.b; + else + b = (UBits)(SBits)bn.n; +#elif defined(LUA_NUMBER_FLOAT) +#error "A 'float' lua_Number type is incompatible with this library" +#else +#error "Unknown number type, check LUA_NUMBER_* in luaconf.h" +#endif +#if LUA_VERSION_NUM < 502 + if (b == 0 && !lua_isnumber(L, idx)) { + luaL_typerror(L, idx, "number"); + } +#endif + return b; +} + +/* Return bit type. */ +#define BRET(b) lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1; + +static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) } +static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) } + +#define BIT_OP(func, opr) \ + static int func(lua_State *L) { int i; UBits b = barg(L, 1); \ + for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) } +BIT_OP(bit_band, &=) +BIT_OP(bit_bor, |=) +BIT_OP(bit_bxor, ^=) + +#define bshl(b, n) (b << n) +#define bshr(b, n) (b >> n) +#define bsar(b, n) ((SBits)b >> n) +#define brol(b, n) ((b << n) | (b >> (32-n))) +#define bror(b, n) ((b << (32-n)) | (b >> n)) +#define BIT_SH(func, fn) \ + static int func(lua_State *L) { \ + UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) } +BIT_SH(bit_lshift, bshl) +BIT_SH(bit_rshift, bshr) +BIT_SH(bit_arshift, bsar) +BIT_SH(bit_rol, brol) +BIT_SH(bit_ror, bror) + +static int bit_bswap(lua_State *L) +{ + UBits b = barg(L, 1); + b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24); + BRET(b) +} + +static int bit_tohex(lua_State *L) +{ + UBits b = barg(L, 1); + UBits n = lua_isnone(L, 2) ? 8 : barg(L, 2); + const char *hexdigits = "0123456789abcdef"; + char buf[8]; + int i; + if ((SBits)n < 0) { n = ~n+1; hexdigits = "0123456789ABCDEF"; } + if (n > 8) n = 8; + for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } + lua_pushlstring(L, buf, (size_t)n); + return 1; +} + +static const struct luaL_Reg bit_funcs[] = { + { "tobit", bit_tobit }, + { "bnot", bit_bnot }, + { "band", bit_band }, + { "bor", bit_bor }, + { "bxor", bit_bxor }, + { "lshift", bit_lshift }, + { "rshift", bit_rshift }, + { "arshift", bit_arshift }, + { "rol", bit_rol }, + { "ror", bit_ror }, + { "bswap", bit_bswap }, + { "tohex", bit_tohex }, + { NULL, NULL } +}; + +/* Signed right-shifts are implementation-defined per C89/C99. +** But the de facto standard are arithmetic right-shifts on two's +** complement CPUs. This behaviour is required here, so test for it. +*/ +#define BAD_SAR (bsar(-8, 2) != (SBits)-2) + +LUALIB_API int luaopen_bit(lua_State *L) +{ + UBits b; + lua_pushnumber(L, (lua_Number)1437217655L); + b = barg(L, -1); + if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */ + const char *msg = "compiled with incompatible luaconf.h"; +#ifdef LUA_NUMBER_DOUBLE +#ifdef _WIN32 + if (b == (UBits)1610612736L) + msg = "use D3DCREATE_FPU_PRESERVE with DirectX"; +#endif + if (b == (UBits)1127743488L) + msg = "not compiled with SWAPPED_DOUBLE"; +#endif + if (BAD_SAR) + msg = "arithmetic right-shift broken"; + luaL_error(L, "bit library self-test failed (%s)", msg); + } +#if LUA_VERSION_NUM < 502 + luaL_register(L, "bit", bit_funcs); +#else + luaL_newlib(L, bit_funcs); +#endif + return 1; +} + diff --git a/lua/src/linit.c b/lua/src/linit.c index c1f90df..f580779 100644 --- a/lua/src/linit.c +++ b/lua/src/linit.c @@ -23,6 +23,7 @@ static const luaL_Reg lualibs[] = { {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_DBLIBNAME, luaopen_debug}, + {LUA_BITLIBNAME, luaopen_bit}, {NULL, NULL} }; diff --git a/lua/src/lualib.h b/lua/src/lualib.h index 469417f..e0369d1 100644 --- a/lua/src/lualib.h +++ b/lua/src/lualib.h @@ -39,6 +39,8 @@ LUALIB_API int (luaopen_debug) (lua_State *L); #define LUA_LOADLIBNAME "package" LUALIB_API int (luaopen_package) (lua_State *L); +#define LUA_BITLIBNAME "bit" +LUALIB_API int (luaopen_bit)(lua_State* L); /* open all previous libraries */ LUALIB_API void (luaL_openlibs) (lua_State *L); diff --git a/sgutil/lua/dump_npk_list.lua b/sgutil/lua/dump_npk_list.lua index d3826dc..29b28aa 100644 --- a/sgutil/lua/dump_npk_list.lua +++ b/sgutil/lua/dump_npk_list.lua @@ -1,76 +1,52 @@ --print npk file list to file --[[ -npkFileName(string): npk file path name(utf8) -listFileName(string): list output path name(utf8) -keyName(boolean): print key name -npkName(boolean): print npk file name -npkBase(boolean): print npk base dir name -fileSize(boolean): print file size -fileCRC(boolean): print file crc -fileOffset(boolean): print file offset - -return(boolean): is success +local M = require("dump_npk_list") +local ret = M.dump_npk_file_list( + { + "D:\\WeGameApps\\地下城与勇士:创新世纪\\ImagePacks2\\sprite_character_archer_effect_air.NPK", + "D:\\WeGameApps\\地下城与勇士:创新世纪\\ImagePacks2\\sprite_interface2_event_20160927_national_day_firework.NPK" + }, + "d:\\output.txt", + false, false, false, false, false +) --]] local M={} -function M.dump_npk_file_list(npkFileName, listFileName, npkBase, npkName, keyName, fileOffset, fileSize, fileCRC) - local npk = createNPKFile(); +function M.dump_npk_file_list(npkFileNames, listFileName, npkBase, npkName, fileOffset, fileSize, fileCRC) + + local finalList = createEmptyFileList() - local ret = npk:openPakFile(npkFileName) - if(not ret) then - return false + for i,npkFileName in pairs(npkFileNames) do + local npk = createNPKFile(); + + local ret = npk:openPakFile(npkFileName) + if(not ret) then + return false + end + + local fileList = npk:generateFullInfoList() + if(not fileList)then + return false + end + + ret = finalList:mergeOtherListInto(fileList, true) + if(not ret) then + return false + end + destroyFileList(fileList) + npk:closePakFile() + destroyNPKFile(npk) end - listOutputFile = io.open(listFileName, "w") - fileList = npk:generateFullInfoList(); - - counts = fileList:getFileCounts() + local flags = 0 + if fileCRC then flags = 1 end + if fileSize then flags = flags + bit.lshift(1, 1) end + if fileOffset then flags = flags + bit.lshift(1, 2) end + if npkName then flags = flags + bit.lshift(1, 3) end + if npkBase then flags = flags + bit.lshift(1, 4) end - for i=0, counts-1, 1 do - local fileInfo = fileList:getFileItem(i) - - outputLine="" - - if(npkBase) then - if(#outputLine>0) then outputLine = outputLine .. "|" end - outputLine = outputLine .. fileInfo:npkBase(); - end - - if(npkName) then - if(#outputLine>0) then outputLine = outputLine .. "|" end - outputLine = outputLine .. fileInfo:npkName(); - end - - if(keyName) then - if(#outputLine>0) then outputLine = outputLine .. "|" end - outputLine = outputLine .. fileInfo:keyName(); - end - - if(fileOffset) then - if(#outputLine>0) then outputLine = outputLine .. "|" end - outputLine = outputLine .. tostring(fileInfo.fileOffset); - end - - if(fileSize) then - if(#outputLine>0) then outputLine = outputLine .. "|" end - outputLine = outputLine .. tostring(fileInfo.fileSize); - end - - if(fileCRC) then - if(#outputLine>0) then outputLine = outputLine .. "|" end - outputLine = outputLine .. tostring(fileInfo.fileCRC); - end - - if(#outputLine>0) then - listOutputFile:write(outputLine .. "\n") - end - end - - listOutputFile:close() - - destroyFileList(fileList) - npk:closePakFile() - destroyNPKFile(npk) + finalList:dumpToLocalFile(listFileName, flags) + destroyFileList(finalList) return true end diff --git a/sgutil/lua/extrace_npk_file.lua b/sgutil/lua/extrace_npk_file.lua index ca40d26..84ee00e 100644 --- a/sgutil/lua/extrace_npk_file.lua +++ b/sgutil/lua/extrace_npk_file.lua @@ -4,6 +4,13 @@ npkFileName The path to the NPK archive file to be extracted. outputPath The path to the output directory where files will be extracted. return true if extraction succeeds; false otherwise. --]] +--[[ +local M = require("extrace_npk_file") +local ret = M.extract_npk_files("D:\\WeGameApps\\地下城与勇士:创新世纪\\ImagePacks2\\sprite_character_archer_effect_air.NPK", + "D:\\_temp\\output" +) +--]] + local M={} function M.extract_npk_files(npkFileName, outputPath) local npk = createNPKFile(); diff --git a/sgutil/sgu_lua_npk_file.cpp b/sgutil/sgu_lua_npk_file.cpp index c7613bb..39e7535 100644 --- a/sgutil/sgu_lua_npk_file.cpp +++ b/sgutil/sgu_lua_npk_file.cpp @@ -13,11 +13,15 @@ extern "C" //////////////////////////////////////////////////////////////////////////////////// void registerNPKLuaLibs(lua_State* L) { + //register global functions + lua_tinker::def(L, "getLastErrorCode", &NPK::getLastErrorCode); + lua_tinker::def(L, "getLastErrorMessage", &NPK::getLastErrorMessage); + lua_tinker::def(L, "createNPKFile", &LuaNPKFile::create); lua_tinker::def(L, "destroyNPKFile", &LuaNPKFile::destroy); + lua_tinker::def(L, "createEmptyFileList", &LuaNPKFileList::createEmpty); lua_tinker::def(L, "destroyFileList", &LuaNPKFileList::destroy); - lua_tinker::def(L, "getLastErrorMessage", &NPK::getLastErrorMessage); lua_tinker::class_add(L, "NPKFile"); lua_tinker::class_def(L, "openPakFile", &LuaNPKFile::openPakFile); @@ -42,8 +46,13 @@ void registerNPKLuaLibs(lua_State* L) lua_tinker::class_mem(L, "fileCRC", &LuaNPKFileItemFullInfo::fileCRC); lua_tinker::class_add(L, "LuaNPKFileList"); + lua_tinker::class_def(L, "loadListFromFile", &LuaNPKFileList::loadListFromFile); + lua_tinker::class_def(L, "dumpToLocalFile", &LuaNPKFileList::dumpToLocalFile); + lua_tinker::class_def(L, "mergeOtherListInto", &LuaNPKFileList::mergeOtherListInto); + lua_tinker::class_def(L, "applyToLocalNPKFiles", &LuaNPKFileList::applyToLocalNPKFiles); lua_tinker::class_def(L, "getFileCounts", &LuaNPKFileList::getFileCounts); - lua_tinker::class_def(L, "getFileItem", &LuaNPKFileList::getFileItem); + lua_tinker::class_def(L, "getFileItemFromIndex", &LuaNPKFileList::getFileItemFromIndex); + lua_tinker::class_def(L, "getFileItemFromName", &LuaNPKFileList::getFileItemFromName); lua_tinker::class_add(L, "NPKFileStream"); lua_tinker::class_def(L, "name", &LuaNPKFileStream::name); @@ -189,12 +198,67 @@ void LuaNPKFileList::destroy(LuaNPKFileList* instance) delete instance; } +bool LuaNPKFileList::loadListFromFile(const char* wszListFile/*utf8*/, const char* prefix, uint32_t flags, bool bEnableDuplicate) +{ + bool bNpkBase = (flags >> 4) & 1; + bool bNpkName = (flags >> 3) & 1; + bool bFileOffset = (flags >> 2) & 1; + bool bFileSize = (flags >> 1) & 1; + bool bFileCRC = flags & 1; + + if (m_pFileList) + { + std::wstring wstrListFile = convertUtf8StringToWide(wszListFile); + return m_pFileList->loadListFromFile(wstrListFile.c_str(), prefix, + bNpkBase, bNpkName, bFileOffset, bFileSize, bFileCRC, + bEnableDuplicate); + } + return false; +} + +bool LuaNPKFileList::dumpToLocalFile(const char* wszListFile/*utf8*/, uint32_t flags) +{ + bool bNpkBase = (flags >> 4) & 1; + bool bNpkName = (flags >> 3) & 1; + bool bFileOffset = (flags >> 2) & 1; + bool bFileSize = (flags >> 1) & 1; + bool bFileCRC = flags & 1; + if (m_pFileList) + { + std::wstring wstrListFile = convertUtf8StringToWide(wszListFile); + return m_pFileList->dumpToLocalFile(wstrListFile.c_str(), + bNpkBase, bNpkName, bFileOffset, bFileSize, bFileCRC + ); + } + return false; +} + +bool LuaNPKFileList::mergeOtherListInto(const LuaNPKFileList* sourceFileList, bool bEnableDuplicate) +{ + if (m_pFileList) + { + return m_pFileList->mergeOtherListInto(sourceFileList->m_pFileList, bEnableDuplicate); + } + return false; +} + +bool LuaNPKFileList::applyToLocalNPKFiles(const char* wszNPKBase/*utf8*/) +{ + if (m_pFileList) + { + std::wstring strNPKBase = convertUtf8StringToWide(wszNPKBase); + return m_pFileList->applyToLocalNPKFiles(strNPKBase.c_str()); + } + return false; +} + int32_t LuaNPKFileList::getFileCounts(void) const { return m_pFileList ? m_pFileList->getFileCounts() : 0; } -LuaNPKFileItemFullInfo LuaNPKFileList::getFileItem(int32_t index) const + +LuaNPKFileItemFullInfo LuaNPKFileList::getFileItemFromIndex(int32_t index) const { LuaNPKFileItemFullInfo fullInfo; if (m_pFileList) @@ -203,3 +267,14 @@ LuaNPKFileItemFullInfo LuaNPKFileList::getFileItem(int32_t index) const } return fullInfo; } + +LuaNPKFileItemFullInfo LuaNPKFileList::getFileItemFromName(const char* szKeyName) const +{ + LuaNPKFileItemFullInfo fullInfo; + if (m_pFileList) + { + m_pFileList->getFileItem(szKeyName, &fullInfo); + } + return fullInfo; +} + diff --git a/sgutil/sgu_lua_npk_file.h b/sgutil/sgu_lua_npk_file.h index 11f60d7..f0f4405 100644 --- a/sgutil/sgu_lua_npk_file.h +++ b/sgutil/sgu_lua_npk_file.h @@ -39,8 +39,14 @@ public: static LuaNPKFileList* createEmpty(); static void destroy(LuaNPKFileList* instance); public: + bool loadListFromFile(const char* wszListFile/*utf8*/, const char* prefix, uint32_t flags, bool bEnableDuplicate); + bool dumpToLocalFile(const char* wszListFile/*utf8*/, uint32_t flags); + bool mergeOtherListInto(const LuaNPKFileList* sourceFileList, bool bEnableDuplicate); + bool applyToLocalNPKFiles(const char* wszNPKBase/*utf8*/); + int32_t getFileCounts(void) const; - LuaNPKFileItemFullInfo getFileItem(int32_t index) const; + LuaNPKFileItemFullInfo getFileItemFromIndex(int32_t index) const; + LuaNPKFileItemFullInfo getFileItemFromName(const char* szKeyName) const; public: NPK::IFileList* m_pFileList = nullptr; diff --git a/sgutil/sgu_mode_run_lua_file.cpp b/sgutil/sgu_mode_run_lua_file.cpp index 7bd93c2..26f471a 100644 --- a/sgutil/sgu_mode_run_lua_file.cpp +++ b/sgutil/sgu_mode_run_lua_file.cpp @@ -15,13 +15,18 @@ extern "C" bool run_lua_file(const char* szLuaFilename) { + //NPK::IFileList* pNpkList = NPK::createEmptyFileList(); + //pNpkList->loadListFromFile(L"d:\\output.txt", "sprite/", + // true, true, true, true, true, + // false); + + //pNpkList->applyToLocalNPKFiles(L"D:\\WeGameApps\\µØÏ³ÇÓëÓÂÊ¿£º´´ÐÂÊÀ¼Í\\ImagePacks2"); + //NPK::destoryFileList(pNpkList); + //return true; + lua_State* L = lua_open(); luaL_openlibs(L); - //register global functions - lua_tinker::def(L, "getLastErrorCode", &NPK::getLastErrorCode); - lua_tinker::def(L, "getLastErrorMessage", &NPK::getLastErrorMessage); - //register classes registerNPKLuaLibs(L); registerUtilsLuaLibs(L);