#include "StdAfx.h" #include "TurbineFormats.h" #pragma comment(lib, "psapi.lib") namespace Random { int m_iSeed; void Init() { m_iSeed = (signed)((unsigned int)(time(0)*12345) << 2) - 144810491; } uint32_t GenRandom15() { m_iSeed = (m_iSeed * 214013) + 2531011; uint32_t dwRandom15 = (unsigned)m_iSeed; dwRandom15 >>= 16; dwRandom15 &= 0x7FFF; return dwRandom15; } uint32_t GenRandom32() { uint32_t dwRandom32 = 0; dwRandom32 |= GenRandom15(); dwRandom32 <<= 15; dwRandom32 |= GenRandom15(); dwRandom32 <<= 15; dwRandom32 |= GenRandom15(); return dwRandom32; } uint32_t GenUInt(uint32_t min, uint32_t max) { if (max <= min) return min; unsigned int range = max - min; return (min + (GenRandom32() % (range + 1))); } int32_t GenInt(int32_t min, int32_t max) { if (max <= min) return min; unsigned int range = (unsigned)(max - min); return (min + (int)(GenRandom32() % (range + 1))); } double GenFloat(double min, double max) { if (max <= min) return min; double range = max - min; double value = min + (range * ((double)GenRandom32() / 0xFFFFFFFF)); return value; } float GenFloat(float min, float max) { if (max <= min) return min; double range = max - min; double value = min + (range * ((double)GenRandom32() / 0xFFFFFFFF)); return (float)value; } } void EnumerateFolderFilePaths(std::list &results, const char *basePath, const char *fileMask, bool bSubFolders) { std::string basePathStr(basePath); basePathStr += "\\"; WIN32_FIND_DATA data; HANDLE hFind = FindFirstFile((basePathStr + fileMask).c_str(), &data); if (hFind != INVALID_HANDLE_VALUE) { do { if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { continue; } results.push_back(basePathStr + data.cFileName); } while (FindNextFile(hFind, &data)); CloseHandle(INVALID_HANDLE_VALUE); } if (bSubFolders) { hFind = FindFirstFile((basePathStr + "*").c_str(), &data); if (hFind != INVALID_HANDLE_VALUE) { do { if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { if (!strcmp(data.cFileName, ".") || !strcmp(data.cFileName, "..")) continue; std::string subFolderStr; subFolderStr = basePathStr + data.cFileName; EnumerateFolderFilePaths(results, subFolderStr.c_str(), fileMask, true); continue; } } while (FindNextFile(hFind, &data)); CloseHandle(INVALID_HANDLE_VALUE); } } } char NibbleToChar(int n) { if (n < 10) return '0' + n; else return 'a' + (n - 10); } char NibbleToCharUCase(int n) { if (n < 10) return '0' + n; else return 'A' + (n - 10); } char *DataToHexString(const void *input, unsigned int inputlen, char *output) { uint8_t *data = (uint8_t *)input; for (unsigned int i = 0; i < inputlen; i++) { output[(i << 1) + 0] = NibbleToChar((data[i] & 0xF0) >> 4); output[(i << 1) + 1] = NibbleToChar((data[i] & 0x0F) >> 0); } output[inputlen << 1] = '\0'; return output; } bool LoadDataFromFile(const char *filepath, BYTE **data, DWORD *length) { *data = NULL; *length = 0; FILE *fp = fopen(filepath, "rb"); if (fp) { fseek(fp, 0, SEEK_END); long _fileSize = ftell(fp); fseek(fp, 0, SEEK_SET); if (_fileSize < 0) _fileSize = 0; DWORD fileSize = (DWORD)_fileSize; BYTE *fileData = new BYTE[fileSize]; fread(fileData, fileSize, 1, fp); fclose(fp); *data = fileData; *length = fileSize; return true; } return false; } bool LoadDataFromCompressed_(BYTE *input_data, DWORD input_length, BYTE **data, DWORD *length, DWORD magic1, DWORD magic2) { *data = NULL; *length = 0; DWORD packing = magic1; for (DWORD i = 0; i < (input_length >> 2); i++) { ((DWORD *)input_data)[i] += ((i + 1) * packing); packing ^= magic2; } DWORD decompressed_size = *((DWORD *)input_data); BYTE *compressed_buffer = input_data + sizeof(DWORD); DWORD compressed_size = input_length - sizeof(DWORD); *data = new BYTE[decompressed_size]; *length = decompressed_size; bool success = true; if (Z_OK != uncompress(*data, length, compressed_buffer, compressed_size)) { delete[](*data); *data = NULL; *length = 0; success = false; } return success; } bool LoadDataFromCompressedFile(const char *filepath, BYTE **data, DWORD *length, DWORD magic1, DWORD magic2) { *data = NULL; *length = 0; BYTE *input_data = NULL; DWORD input_length = 0; if (LoadDataFromFile(filepath, &input_data, &input_length)) { bool success = LoadDataFromCompressed_(input_data, input_length, data, length, magic1, magic2); delete[] input_data; return success; } return false; } long FindNeedle(void *haystack, unsigned int haystacklength, void *needle, unsigned int needlelength) { if (haystacklength < needlelength) return -1; if (!needlelength) return -1; BYTE *dataPos = (BYTE *)haystack; BYTE *dataEnd = (dataPos + haystacklength - needlelength); bool found = false; while (dataPos <= dataEnd) { if (!memcmp(dataPos, needle, needlelength)) { found = true; break; } dataPos++; } if (!found) return -1; return (dataPos - (BYTE *)haystack); } // returns a string of "Xmo, Xd, Xh, Xm, Xs" std::string TimeToString(int seconds) { int mo = seconds / 2629800; // seconds in a month int leftover = seconds % 2629800; int d = leftover / 86400; // seconds in a day leftover %= 86400; int h = leftover / 3600; // seconds in an hour leftover %= 3600; int m = leftover / 60; // seconds in a minute leftover %= 60; int s = leftover; std::string out = ""; if (mo) out += csprintf("%dmo ", mo); if (d) out += csprintf("%dd ", d); if (h) out += csprintf("%dh ", h); if (m) out += csprintf("%dm ", m); out += csprintf("%ds", s); return out; } bool ReplaceString(std::string& str, const std::string& from, const std::string& to) { size_t start_pos = str.find(from); if (start_pos == std::string::npos) return false; str.replace(start_pos, from.length(), to); return true; } std::string ReplaceInString(std::string subject, const std::string& search, const std::string& replace) { size_t pos = 0; while ((pos = subject.find(search, pos)) != std::string::npos) { subject.replace(pos, search.length(), replace); pos += replace.length(); } return subject; } static char szReadBuffer[1024]; static char szWriteBuffer[600]; char* csprintf(const char *format, ...) { szReadBuffer[0] = 0; va_list args; va_start(args, format); _vsnprintf(szReadBuffer, 1024, format, args); va_end(args); szReadBuffer[1023] = '\0'; return szReadBuffer; } char *timestamp() { static char result[64]; tm *beef; time_t cake; time(&cake); beef = localtime(&cake); if (beef) sprintf(result, "%.2d:%.2d:%.2d", beef->tm_hour, beef->tm_min, beef->tm_sec); else result[0] = 0; return result; } char *timestampDateString(time_t ts) { static char result[64]; tm *beef; time_t cake = ts; beef = localtime(&cake); if (beef) sprintf(result, "%d/%02d/%d %02d:%02d:%02d", beef->tm_mon + 1, beef->tm_mday, beef->tm_year + 1900, beef->tm_hour, beef->tm_min, beef->tm_sec); else result[0] = 0; return result; } char *timestampDateStringForFileName(time_t ts) { static char result[64]; tm *beef; time_t cake = ts; beef = localtime(&cake); if (beef) sprintf(result, "%04d_%02d_%02d__%02d_%02d_%02d", beef->tm_year + 1900, beef->tm_mon + 1, beef->tm_mday, beef->tm_hour, beef->tm_min, beef->tm_sec); else result[0] = 0; return result; } unsigned long ResolveIPFromHost(const char *host) { ULONG ipaddr; // Check if it's in IP format. ipaddr = ::inet_addr(host); if (ipaddr && ipaddr != INADDR_NONE) return (unsigned long)ipaddr; // Try to resolve an IP address. LPHOSTENT lphost; lphost = gethostbyname(host); if (lphost != NULL) { ipaddr = ((LPIN_ADDR)lphost->h_addr)->s_addr; if (ipaddr && ipaddr != INADDR_NONE) return (unsigned long)ipaddr; } return 0; } unsigned long GetLocalIP() { char hostname[256]; gethostname(hostname, 256); DWORD hostaddr = *((DWORD *)gethostbyname(hostname)->h_addr); return *(unsigned long *)gethostbyname(hostname)->h_addr; } std::string GetLocalIPString() { unsigned long localIP = GetLocalIP(); return inet_ntoa(*(in_addr *)&localIP); } std::string DebugBytesToString(void *_data, unsigned int len) { BYTE *data = (BYTE *)_data; std::string strBytes; for (unsigned int i = 0; i < len; i++) { char temp[3]; sprintf(temp, "%02X", data[i]); strBytes += temp; if (!((i + 1) % 16)) strBytes += "\n"; else strBytes += " "; } if (len % 16) { strBytes += "\n"; } return strBytes; } void MsgBox(UINT type, const char *format, ...) { szWriteBuffer[0] = 0; va_list args; va_start(args, format); _vsnprintf(szWriteBuffer, 1024, format, args); va_end(args); HWND hWnd = g_pGlobals ? g_pGlobals->GetWindowHandle() : NULL; MessageBox(hWnd, szWriteBuffer, "GDL", MB_OK | type); } void MsgBox(const char *format, ...) { szWriteBuffer[0] = 0; va_list args; va_start(args, format); _vsnprintf(szWriteBuffer, 1024, format, args); va_end(args); MessageBox(NULL, szWriteBuffer, "GDL", MB_OK); } void MsgBoxError(DWORD dwError, const char* event) { LPVOID lpMsgBuf; if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL)) { MsgBox(MB_ICONHAND, "Unknown error #%lu %s", dwError, event); return; } MsgBox(MB_ICONHAND, "Error #%lu %s:\r\n%s", dwError, event, lpMsgBuf); LocalFree(lpMsgBuf); } #define REGLOC HKEY_LOCAL_MACHINE, "Software\\GDL" BOOL SaveConfigKey(const char* Key, DWORD value) { BOOL bReturn = FALSE; HKEY hKey; if (RegCreateKeyEx(REGLOC, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS) { if (SUCCEEDED(RegSetValueEx(hKey, Key, NULL, REG_DWORD, (BYTE *)&value, sizeof(DWORD)))) bReturn = TRUE; RegCloseKey(hKey); } return bReturn; } BOOL SaveConfigKey(const char* Key, const char* value) { BOOL bReturn = FALSE; HKEY hKey; if (RegCreateKeyEx(REGLOC, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS) { if (SUCCEEDED(RegSetValueEx(hKey, Key, NULL, REG_SZ, (BYTE*)value, (DWORD)strlen(value) + 1))) bReturn = TRUE; RegCloseKey(hKey); } return bReturn; } BOOL ReadConfigKey(const char* Key, DWORD* value) { DWORD type = REG_DWORD; DWORD size = sizeof(DWORD); BOOL bReturn = FALSE; HKEY hKey; if (RegOpenKeyEx(REGLOC, NULL, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { if (!RegQueryValueEx(hKey, Key, NULL, &type, (BYTE*)value, &size)) bReturn = TRUE; RegCloseKey(hKey); } return bReturn; } BOOL ReadConfigKey(const char* Key, char* value, DWORD size) { DWORD type = REG_SZ; BOOL bReturn = FALSE; HKEY hKey; if (RegOpenKeyEx(REGLOC, NULL, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { if (!RegQueryValueEx(hKey, Key, NULL, &type, (BYTE*)value, &size)) bReturn = TRUE; RegCloseKey(hKey); } return bReturn; } bool FileExists(const char *filePath) { DWORD dwAttrib = GetFileAttributes(filePath); return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } void strtrim(char *szText) { //how many left spaces are leading? int leading = 0; while (szText[leading] == ' ') leading++; if (leading) { //shift left int i = leading; while (1) { szText[i - leading] = szText[i]; if (szText[i] == 0) break; i++; } } int pos = (int)strlen(szText) - 1; //remove trailing spaces while ((pos >= 0) && szText[pos] == ' ') szText[pos--] = 0; } BOOL strmask(const char* szTest, const char* szMask) { //We need to someday create a function for validating a string mask. return FALSE; } long fsize(FILE* fileptr) { long lOld, lSize; lOld = ftell(fileptr); fseek(fileptr, 0, SEEK_END); lSize = ftell(fileptr); fseek(fileptr, lOld, SEEK_SET); return lSize; } float NorthSouth(char *szCoord) { strlwr(szCoord); strtrim(szCoord); int len = (int)strlen(szCoord); if (len < 1) return 0; char *end = &szCoord[len - 1]; if (*end == ',') { len--; if (len < 1) return 0; *end = '\0'; end = &szCoord[len - 1]; } char NS = *end; *end = 0; strtrim(szCoord); float dir = 0.0f; if (NS == 'n') dir = 1.0f; else if (NS == 's') dir = -1.0f; float coord = 0.0f; sscanf(szCoord, "%f", &coord); return coord * dir; } float EastWest(char *szCoord) { strlwr(szCoord); strtrim(szCoord); int len = (int)strlen(szCoord); if (len < 1) return 0; char *end = &szCoord[len - 1]; char EW = *end; *end = 0; strtrim(szCoord); float dir = 0.0f; if (EW == 'e') dir = 1.0f; else if (EW == 'w') dir = -1.0f; float coord = 0.0f; sscanf(szCoord, "%f", &coord); return coord * dir; } DWORD GetCellFromBase(DWORD BaseX, DWORD BaseY) { BYTE blockx = (BYTE)(BaseX >> 3); BYTE blocky = (BYTE)(BaseY >> 3); BYTE cellx = (BYTE)(BaseX & 7); BYTE celly = (BYTE)(BaseY & 7); WORD block = (blockx << 8) | (blocky); WORD cell = (cellx << 3) | (celly); DWORD dwCell = (block << 16) | (cell + 1); return dwCell; } bool GetLocation(double NS, double EW, Position &pos) { NS -= 0.5f; EW -= 0.5f; NS *= 10.0f; EW *= 10.0f; DWORD basex = (DWORD)(EW + 0x400); DWORD basey = (DWORD)(NS + 0x400); if (long(basex) < 0 || long(basey) < 0 || basex >= 0x7F8 || basey >= 0x7F8) { //Out of bounds. pos = Position(); return false; } DWORD dwCell = GetCellFromBase(basex, basey); float xOffset = ((basex & 7) * 24.0f) + 12; float yOffset = ((basey & 7) * 24.0f) + 12; pos = Position(dwCell, Vector(xOffset, yOffset, CalcSurfaceZ(dwCell, xOffset, yOffset))); return true; } // Water blocks are not passable! BOOL IsWaterBlock(BlockData *pBlock) { for (unsigned int x = 0; x < 9; x++) { for (unsigned int y = 0; y < 9; y++) { if ((pBlock->wSurface[x][y] & 0x50) != 0x50) return FALSE; } } return TRUE; } // BOOL IsWaterBlock(DWORD dwCell) { dwCell &= 0xFFFF0000; dwCell |= 0x0000FFFF; TURBINEFILE *pFile = g_pCell->GetFile(dwCell); if (!pFile) return FALSE; BOOL bResult = IsWaterBlock((BlockData*)pFile->GetData()); delete pFile; return bResult; } BOOL HasObjectBlock(BlockData *pBlock) { return ((pBlock->bObject) ? TRUE : FALSE); } BOOL HasObjectBlock(DWORD dwCell) { dwCell &= 0xFFFF0000; dwCell |= 0x0000FFFF; TURBINEFILE *pFile = g_pCell->GetFile(dwCell); if (!pFile) return FALSE; BOOL bResult = HasObjectBlock((BlockData*)pFile->GetData()); delete pFile; return bResult; } float CalcSurfaceZ(DWORD dwCell, float xOffset, float yOffset, bool bUseLCell) { TURBINEFILE *pFile = g_pCell->GetFile((dwCell & 0xFFFF0000) | 0xFFFF); if (!pFile) return 0; WORD cell = CELL_WORD(dwCell); int minix = (cell >> 3) & 7; int miniy = (cell >> 0) & 7; if (bUseLCell) { xOffset -= (24 * minix); yOffset -= (24 * miniy); } BlockData *pBlock = (BlockData*)pFile->GetData(); Vector P1(0, 24, LandDefs::Land_Height_Table[pBlock->bHeight[minix][miniy + 1]] + 0.005f); Vector P2; Vector P3(24, 0, LandDefs::Land_Height_Table[pBlock->bHeight[minix + 1][miniy]] + 0.005f); if ((xOffset + yOffset) < 1.0f) P2 = Vector(0, 0, LandDefs::Land_Height_Table[pBlock->bHeight[minix][miniy]] + 0.005f); else P2 = Vector(24, 24, LandDefs::Land_Height_Table[pBlock->bHeight[minix + 1][miniy + 1]] + 0.005f); delete pFile; return FindVectorZ(P1, P2, P3, xOffset, yOffset); } DWORD64 GetProcessMemoryUsage() { PROCESS_MEMORY_COUNTERS_EX procMem; memset(&procMem, 0, sizeof(procMem)); GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&procMem, sizeof(procMem)); return procMem.PrivateUsage; } DWORD64 GetFreeMemory() { MEMORYSTATUSEX status; status.dwLength = sizeof(status); GlobalMemoryStatusEx(&status); return status.ullAvailPhys; } DWORD64 GetTotalMemory() { MEMORYSTATUSEX status; status.dwLength = sizeof(status); GlobalMemoryStatusEx(&status); return status.ullTotalPhys; } // strictness 1 = chat, strictness 2 = player names, titles, allegiance names bool containsBadCharacters(std::string input, int strictness) { std::string goodChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'- "; if (strictness == 1) { goodChars += "!\"£$%^&*()_-+={}[]:;<>,.?/@'~#`¬|\\"; } for (auto c : input) { if (goodChars.find(c) != goodChars.npos) { continue; } else return true; } return false; }