MiscFunctions.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "../common/debug.h"
  17. #include "../common/Log.h"
  18. #include "MiscFunctions.h"
  19. #include <string.h>
  20. #include <time.h>
  21. #include <math.h>
  22. #include <chrono>
  23. #ifndef WIN32
  24. #include <netinet/in.h>
  25. #include <sys/socket.h>
  26. #endif
  27. #include <iostream>
  28. #include <iomanip>
  29. #ifdef WIN32
  30. #include <io.h>
  31. #endif
  32. #include "../common/timer.h"
  33. #include "../common/seperator.h"
  34. #include "../common/packet_dump.h"
  35. #include <algorithm>
  36. using namespace std;
  37. #ifndef PATCHER
  38. extern map<int16, int16> EQOpcodeVersions;
  39. #endif
  40. #ifdef WIN32
  41. #include <WinSock2.h>
  42. #include <windows.h>
  43. #define snprintf _snprintf
  44. #define vsnprintf _vsnprintf
  45. #define strncasecmp _strnicmp
  46. #define strcasecmp _stricmp
  47. #else
  48. #include <stdlib.h>
  49. #include <ctype.h>
  50. #include <stdarg.h>
  51. #include <sys/types.h>
  52. #include <sys/time.h>
  53. #ifdef FREEBSD //Timothy Whitman - January 7, 2003
  54. #include <sys/socket.h>
  55. #include <netinet/in.h>
  56. #endif
  57. #include <sys/stat.h>
  58. #include <unistd.h>
  59. #include <netdb.h>
  60. #include <errno.h>
  61. #endif
  62. void CoutTimestamp(bool ms) {
  63. time_t rawtime;
  64. struct tm* gmt_t;
  65. time(&rawtime);
  66. gmt_t = gmtime(&rawtime);
  67. struct timeval read_time;
  68. gettimeofday(&read_time,0);
  69. cout << (gmt_t->tm_year + 1900) << "/" << setw(2) << setfill('0') << (gmt_t->tm_mon + 1) << "/" << setw(2) << setfill('0') << gmt_t->tm_mday << " " << setw(2) << setfill('0') << gmt_t->tm_hour << ":" << setw(2) << setfill('0') << gmt_t->tm_min << ":" << setw(2) << setfill('0') << gmt_t->tm_sec;
  70. if (ms)
  71. cout << "." << setw(3) << setfill('0') << (read_time.tv_usec / 1000);
  72. cout << " GMT";
  73. }
  74. string loadInt32String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_32BitString* eq_string){
  75. buffer += *pos;
  76. int32 size = *(int32*)buffer;
  77. if((size + *pos + sizeof(int16)) > buffer_size){
  78. cout << "Error in loadInt32String: Corrupt packet.\n";
  79. return string("");
  80. }
  81. buffer += sizeof(int32);
  82. string ret((char*)buffer, 0, size);
  83. if(eq_string){
  84. eq_string->size = size;
  85. eq_string->data = ret;
  86. }
  87. *pos += (size + sizeof(int32));
  88. return ret;
  89. }
  90. string loadInt16String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_16BitString* eq_string){
  91. buffer += *pos;
  92. int16 size = *(int16*)buffer;
  93. if((size + *pos + sizeof(int16))> buffer_size){
  94. cout << "Error in loadInt16String: Corrupt packet.\n";
  95. return string("");
  96. }
  97. buffer += sizeof(int16);
  98. string ret((char*)buffer, 0, size);
  99. if(eq_string){
  100. eq_string->size = size;
  101. eq_string->data = ret;
  102. }
  103. *pos += (size + sizeof(int16));
  104. return ret;
  105. }
  106. string loadInt8String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_8BitString* eq_string){
  107. buffer += *pos;
  108. int8 size = *(int8*)buffer;
  109. if((size + *pos + sizeof(int16)) > buffer_size){
  110. cout << "Error in loadInt8String: Corrupt packet.\n";
  111. return string("");
  112. }
  113. buffer += sizeof(int8);
  114. string ret((char*)buffer, 0, size);
  115. if(eq_string){
  116. eq_string->size = size;
  117. eq_string->data = ret;
  118. }
  119. *pos += (size + sizeof(int8));
  120. return ret;
  121. }
  122. sint16 storeInt32String(uchar* buffer, int16 buffer_size, string in_str){
  123. sint16 string_size = in_str.length();
  124. if((string_size + sizeof(int32)) > buffer_size)
  125. return -1;
  126. memcpy(buffer, &string_size, sizeof(int32));
  127. buffer += sizeof(int32);
  128. memcpy(buffer, in_str.c_str(), string_size);
  129. buffer += string_size;
  130. return (buffer_size - (string_size + sizeof(int32)));
  131. }
  132. sint16 storeInt16String(uchar* buffer, int16 buffer_size, string in_str){
  133. sint16 string_size = in_str.length();
  134. if((string_size + sizeof(int16)) > buffer_size)
  135. return -1;
  136. memcpy(buffer, &string_size, sizeof(int16));
  137. buffer += sizeof(int16);
  138. memcpy(buffer, in_str.c_str(), string_size);
  139. buffer += string_size;
  140. return (buffer_size - (string_size + sizeof(int16)));
  141. }
  142. sint16 storeInt8String(uchar* buffer, int16 buffer_size, string in_str){
  143. sint16 string_size = in_str.length();
  144. if((string_size + sizeof(int8)) > buffer_size)
  145. return -1;
  146. memcpy(buffer, &string_size, sizeof(int8));
  147. buffer += sizeof(int8);
  148. memcpy(buffer, in_str.c_str(), string_size);
  149. buffer += string_size;
  150. return (buffer_size - (string_size + sizeof(int8)));
  151. }
  152. sint32 filesize(FILE* fp) {
  153. #ifdef WIN32
  154. return _filelength(_fileno(fp));
  155. #else
  156. struct stat file_stat;
  157. fstat(fileno(fp), &file_stat);
  158. return (sint32) file_stat.st_size;
  159. #endif
  160. }
  161. int32 ResolveIP(const char* hostname, char* errbuf) {
  162. #ifdef WIN32
  163. static InitWinsock ws;
  164. #endif
  165. if (errbuf)
  166. errbuf[0] = 0;
  167. if (hostname == 0) {
  168. if (errbuf)
  169. snprintf(errbuf, ERRBUF_SIZE, "ResolveIP(): hostname == 0");
  170. return 0;
  171. }
  172. struct sockaddr_in server_sin;
  173. #ifdef WIN32
  174. PHOSTENT phostent = NULL;
  175. #else
  176. struct hostent *phostent = NULL;
  177. #endif
  178. server_sin.sin_family = AF_INET;
  179. if ((phostent = gethostbyname(hostname)) == NULL) {
  180. #ifdef WIN32
  181. if (errbuf)
  182. snprintf(errbuf, ERRBUF_SIZE, "Unable to get the host name. Error: %i", WSAGetLastError());
  183. #else
  184. if (errbuf)
  185. snprintf(errbuf, ERRBUF_SIZE, "Unable to get the host name. Error: %s", strerror(errno));
  186. #endif
  187. return 0;
  188. }
  189. #ifdef WIN32
  190. memcpy ((char FAR *)&(server_sin.sin_addr), phostent->h_addr, phostent->h_length);
  191. #else
  192. memcpy ((char*)&(server_sin.sin_addr), phostent->h_addr, phostent->h_length);
  193. #endif
  194. return server_sin.sin_addr.s_addr;
  195. }
  196. #ifdef WIN32
  197. InitWinsock::InitWinsock() {
  198. WORD version = MAKEWORD (1,1);
  199. WSADATA wsadata;
  200. WSAStartup (version, &wsadata);
  201. }
  202. InitWinsock::~InitWinsock() {
  203. WSACleanup();
  204. }
  205. #endif
  206. #ifndef WIN32
  207. const char * itoa(int value) {
  208. static char temp[_ITOA_BUFLEN];
  209. memset(temp, 0, _ITOA_BUFLEN);
  210. snprintf(temp, _ITOA_BUFLEN,"%d", value);
  211. return temp;
  212. }
  213. char * itoa(int value, char *result, int base) {
  214. char *ptr1, *ptr2;
  215. char c;
  216. int tmp_value;
  217. //need a valid base
  218. if (base < 2 || base > 36) {
  219. *result = '\0';
  220. return result;
  221. }
  222. ptr1 = ptr2 = result;
  223. do {
  224. tmp_value = value;
  225. value /= base;
  226. *ptr1++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
  227. }
  228. while (value > 0);
  229. //apply a negative sign if need be
  230. if (tmp_value < 0)
  231. *ptr1++ = '-';
  232. *ptr1-- = '\0';
  233. while (ptr2 < ptr1) {
  234. c = *ptr1;
  235. *ptr1-- = *ptr2;
  236. *ptr2++ = c;
  237. }
  238. return result;
  239. }
  240. #endif
  241. /*
  242. * solar: generate a random integer in the range low-high
  243. * this should be used instead of the rand()%limit method
  244. */
  245. int MakeRandomInt(int low, int high)
  246. {
  247. return (int)MakeRandomFloat((double)low, (double)high + 0.999);
  248. }
  249. int32 hextoi(char* num) {
  250. int len = strlen(num);
  251. if (len < 3)
  252. return 0;
  253. if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
  254. return 0;
  255. int32 ret = 0;
  256. int mul = 1;
  257. for (int i=len-1; i>=2; i--) {
  258. if (num[i] >= 'A' && num[i] <= 'F')
  259. ret += ((num[i] - 'A') + 10) * mul;
  260. else if (num[i] >= 'a' && num[i] <= 'f')
  261. ret += ((num[i] - 'a') + 10) * mul;
  262. else if (num[i] >= '0' && num[i] <= '9')
  263. ret += (num[i] - '0') * mul;
  264. else
  265. return 0;
  266. mul *= 16;
  267. }
  268. return ret;
  269. }
  270. int64 hextoi64(char* num) {
  271. int len = strlen(num);
  272. if (len < 3)
  273. return 0;
  274. if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
  275. return 0;
  276. int64 ret = 0;
  277. int mul = 1;
  278. for (int i=len-1; i>=2; i--) {
  279. if (num[i] >= 'A' && num[i] <= 'F')
  280. ret += ((num[i] - 'A') + 10) * mul;
  281. else if (num[i] >= 'a' && num[i] <= 'f')
  282. ret += ((num[i] - 'a') + 10) * mul;
  283. else if (num[i] >= '0' && num[i] <= '9')
  284. ret += (num[i] - '0') * mul;
  285. else
  286. return 0;
  287. mul *= 16;
  288. }
  289. return ret;
  290. }
  291. float MakeRandomFloat(float low, float high)
  292. {
  293. #ifdef _WIN32
  294. thread_local bool seeded = false;
  295. #else
  296. static bool seeded = false;
  297. #endif
  298. float diff = high - low;
  299. if(!diff) return low;
  300. if(diff < 0)
  301. diff = 0 - diff;
  302. if(!seeded)
  303. {
  304. srand(time(0) * (time(0) % (int)diff));
  305. seeded = true;
  306. }
  307. return (rand() / (float)RAND_MAX * diff + (low > high ? high : low));
  308. }
  309. int32 GenerateEQ2Color(float* r, float* g, float* b){
  310. int8 rgb[4] = {0};
  311. rgb[0] = (int8)((*r)*255);
  312. rgb[1] = (int8)((*b)*255);
  313. rgb[2] = (int8)((*g)*255);
  314. int32 color = 0;
  315. memcpy(&color, rgb, sizeof(int32));
  316. return color;
  317. }
  318. int32 GenerateEQ2Color(float* rgb[3]){
  319. return GenerateEQ2Color(rgb[0], rgb[1], rgb[2]);
  320. }
  321. int8 MakeInt8(float* input){
  322. float input2 = *input;
  323. if(input2 < 0)
  324. input2 *= -1;
  325. return (int8)(input2*255);
  326. }
  327. vector<string>* SplitString(string str, char delim){
  328. vector<string>* results = new vector<string>;
  329. int32 pos;
  330. while((pos = str.find_first_of(delim))!= str.npos){
  331. if(pos > 0){
  332. results->push_back(str.substr(0,pos));
  333. }
  334. if(str.length() > pos)
  335. str = str.substr(pos+1);
  336. else
  337. break;
  338. }
  339. if(str.length() > 0)
  340. results->push_back(str);
  341. return results;
  342. }
  343. bool Unpack(uchar* data, uchar* dst, int16 dstLen, int16 version, bool reverse){
  344. int32 srcLen = 0;
  345. memcpy(&srcLen, data, sizeof(int32));
  346. return Unpack(srcLen, data + 4, dst, dstLen, version, reverse);
  347. }
  348. bool Unpack(int32 srcLen, uchar* data, uchar* dst, int16 dstLen, int16 version, bool reverse) {
  349. // int32 srcLen = 0;
  350. // memcpy(&srcLen, data, sizeof(int32));
  351. // data+=4;
  352. if(reverse)
  353. Reverse(data, srcLen);
  354. int16 pos = 0;
  355. int16 real_pos = 0;
  356. while(srcLen && pos < dstLen) {
  357. if(srcLen >= 0 && !srcLen--)
  358. return false;
  359. int8 code = data[real_pos++];
  360. if(code >= 128) {
  361. for(int8 index=0; index<7; index++) {
  362. if(code & 1) {
  363. if(pos >= dstLen)
  364. return false;
  365. if(srcLen >= 0 && !srcLen--)
  366. return false;
  367. dst[pos++] = data[real_pos++];
  368. } else {
  369. if(pos < dstLen) dst[pos++] = 0;
  370. }
  371. code >>= 1;
  372. }
  373. } else {
  374. if(pos + code > dstLen)
  375. return false;
  376. memset(dst+pos, 0, code);
  377. pos+=code;
  378. }
  379. }
  380. return srcLen <= 0;
  381. }
  382. int32 Pack(uchar* data, uchar* src, int16 srcLen, int16 dstLen, int16 version, bool reverse) {
  383. int16 real_pos = 4;
  384. int32 pos = 0;
  385. int32 code = 0;
  386. int codePos = 0;
  387. int codeLen = 0;
  388. int8 zeroLen = 0;
  389. memset(data,0,dstLen);
  390. if (version > 1 && version <= 374)
  391. reverse = false;
  392. while(pos < srcLen) {
  393. if(src[pos] || codeLen) {
  394. if(!codeLen) {
  395. /*if(zeroLen > 5) {
  396. data[real_pos++] = zeroLen;
  397. zeroLen = 0;
  398. }
  399. else if(zeroLen >= 1 && zeroLen<=5){
  400. for(;zeroLen>0;zeroLen--)
  401. codeLen++;
  402. }*/
  403. if (zeroLen) {
  404. data[real_pos++] = zeroLen;
  405. zeroLen = 0;
  406. }
  407. codePos = real_pos;
  408. code = 0;
  409. data[real_pos++] = 0;
  410. }
  411. if(src[pos]) {
  412. data[real_pos++] = src[pos];
  413. code |= 0x80;
  414. }
  415. code >>= 1;
  416. codeLen++;
  417. if(codeLen == 7) {
  418. data[codePos] = int8(0x80 | code);
  419. codeLen = 0;
  420. }
  421. } else {
  422. if(zeroLen == 0x7F) {
  423. data[real_pos++] = zeroLen;
  424. zeroLen = 0;
  425. }
  426. zeroLen++;
  427. }
  428. pos++;
  429. }
  430. if(codeLen) {
  431. code >>= (7 - codeLen);
  432. data[codePos] = int8(0x80 | code);
  433. } else if(zeroLen) {
  434. data[real_pos++] = zeroLen;
  435. }
  436. if(reverse)
  437. Reverse(data + 4, real_pos - 4);
  438. int32 dataLen = real_pos - 4;
  439. memcpy(&data[0], &dataLen, sizeof(int32));
  440. return dataLen + 4;
  441. }
  442. void Reverse(uchar* input, int32 srcLen){
  443. int16 real_pos = 0;
  444. int16 orig_pos = 0;
  445. int8 reverse_count = 0;
  446. while(srcLen > 0 && srcLen < 0xFFFFFFFF){ // XXX it was >=0 before. but i think it was a bug
  447. int8 code = input[real_pos++];
  448. srcLen--;
  449. if(code >= 128) {
  450. for(int8 index=0; index<7; index++) {
  451. if(code & 1) {
  452. if(srcLen >= 0 && !srcLen--)
  453. return;
  454. real_pos++;
  455. reverse_count++;
  456. }
  457. code >>= 1;
  458. }
  459. }
  460. if(reverse_count > 0){
  461. int8 tmp_data[8] = {0};
  462. for(int8 i=0;i<reverse_count;i++){
  463. tmp_data[i] = input[orig_pos + reverse_count-i];
  464. }
  465. memcpy(input + orig_pos + 1, tmp_data, reverse_count);
  466. reverse_count = 0;
  467. }
  468. orig_pos = real_pos;
  469. }
  470. }
  471. void MovementDecode(uchar* dst, uchar* newval, uchar* orig, int16 len){
  472. int16 pos = len;
  473. while(pos--)
  474. dst[pos] = newval[pos] ^ orig[pos];
  475. }
  476. void Decode(uchar* dst, uchar* src, int16 len) {
  477. int16 pos = len;
  478. while(pos--)
  479. dst[pos] ^= src[pos];
  480. memcpy(src, dst, len);
  481. }
  482. void Encode(uchar* dst, uchar* src, int16 len) {
  483. uchar* data = new uchar[len];
  484. int16 pos = len;
  485. while(pos--)
  486. data[pos] = int8(src[pos] ^ dst[pos]);
  487. memcpy(src, dst, len);
  488. memcpy(dst, data, len);
  489. safe_delete_array(data);
  490. }
  491. float TransformToFloat(sint16 data, int8 bits) {
  492. return (float)(data / (float)(1 << bits));
  493. }
  494. sint16 TransformFromFloat(float data, int8 bits) {
  495. return (sint16)(data * (1 << bits));
  496. }
  497. void SetColor(EQ2_Color* color, long data){
  498. memcpy(color, &data, sizeof(EQ2_Color));
  499. }
  500. string ToUpper(string input){
  501. string ret = input;
  502. transform(input.begin(), input.end(), ret.begin(), ::toupper);
  503. return ret;
  504. }
  505. string ToLower(string input){
  506. string ret = input;
  507. transform(input.begin(), input.end(), ret.begin(), ::tolower);
  508. return ret;
  509. }
  510. int32 ParseIntValue(string input){
  511. int32 ret = 0xFFFFFFFF;
  512. try{
  513. if(input.length() > 0){
  514. ret = atoul(input.c_str());
  515. }
  516. }
  517. catch(...){}
  518. return ret;
  519. }
  520. int64 ParseLongLongValue(string input){
  521. int64 ret = 0xFFFFFFFFFFFFFFFF;
  522. try{
  523. if(input.length() > 0){
  524. #ifdef WIN32
  525. ret = _strtoui64(input.c_str(), NULL, 10);
  526. #else
  527. ret = strtoull(input.c_str(), 0, 10);
  528. #endif
  529. }
  530. }
  531. catch(...){}
  532. return ret;
  533. }
  534. map<string, string> TranslateBrokerRequest(string request){
  535. map<string, string> ret;
  536. string key;
  537. string value;
  538. int32 start_pos = 0;
  539. int32 end_pos = 0;
  540. int32 pos = request.find("=");
  541. bool str_val = false;
  542. while(pos < 0xFFFFFFFF){
  543. str_val = false;
  544. key = request.substr(start_pos, pos-start_pos);
  545. if(request.find("|", pos) == pos+1){
  546. pos++;
  547. end_pos = request.find("|", pos+1);
  548. str_val = true;
  549. }
  550. else
  551. end_pos = request.find(" ", pos);
  552. if(end_pos < 0xFFFFFFFF){
  553. value = request.substr(pos+1, end_pos-pos-1);
  554. start_pos = end_pos+1;
  555. if(str_val){
  556. start_pos++;
  557. ret[key] = ToLower(value);
  558. }
  559. else
  560. ret[key] = value;
  561. pos = request.find("=", start_pos);
  562. }
  563. else{
  564. value = request.substr(pos+1);
  565. if(str_val){
  566. start_pos++;
  567. ret[key] = ToLower(value);
  568. }
  569. else
  570. ret[key] = value;
  571. break;
  572. }
  573. }
  574. return ret;
  575. }
  576. int8 CheckOverLoadSize(int32 val){
  577. int8 ret = 1;
  578. if(val >= 0xFFFF) //int32
  579. ret = sizeof(int16) + sizeof(int32);
  580. else if(val >= 0xFF)
  581. ret = sizeof(int8) + sizeof(int16);
  582. return ret;
  583. }
  584. int8 DoOverLoad(int32 val, uchar* data){
  585. int8 ret = 1;
  586. if(val >= 0xFFFF){ //int32
  587. memset(data, 0xFF, sizeof(int16));
  588. memcpy(data + sizeof(int16), &val, sizeof(int32));
  589. ret = sizeof(int16) + sizeof(int32);
  590. }
  591. else if(val >= 0xFF){ //int16
  592. memset(data, 0xFF, sizeof(int8));
  593. memcpy(data + sizeof(int8), &val, sizeof(int16));
  594. ret = sizeof(int8) + sizeof(int16);
  595. }
  596. else
  597. memcpy(data, &val, sizeof(int8));
  598. return ret;
  599. }
  600. /* Treats contiguous spaces as one space. */
  601. int32 CountWordsInString(const char* text) {
  602. int32 words = 0;
  603. if (text && strlen(text) > 0) {
  604. bool on_word = false;
  605. for (int32 i = 0; i < strlen(text); i++) {
  606. char letter = text[i];
  607. if (on_word && !((letter >= 48 && letter <= 57) || (letter >= 65 && letter <= 90) || (letter >= 97 && letter <= 122)))
  608. on_word = false;
  609. else if (!on_word && ((letter >= 48 && letter <= 57) || (letter >= 65 && letter <= 90) || (letter >= 97 && letter <= 122))){
  610. on_word = true;
  611. words++;
  612. }
  613. }
  614. }
  615. return words;
  616. }
  617. bool IsNumber(const char *num) {
  618. size_t len, i;
  619. if (!num)
  620. return false;
  621. len = strlen(num);
  622. if (len == 0)
  623. return false;
  624. for (i = 0; i < len; i++) {
  625. if (!isdigit(num[i]))
  626. return false;
  627. }
  628. return true;
  629. }
  630. void PrintSep(Seperator *sep, const char *name) {
  631. int32 i = 0;
  632. LogWrite(MISC__DEBUG, 0, "Misc", "Printing sep %s", name ? name : "No Name");
  633. if (!sep)
  634. LogWrite(MISC__DEBUG, 0, "Misc", "\tSep is null");
  635. else {
  636. while (sep->arg[i] && strlen(sep->arg[i]) > 0) {
  637. LogWrite(MISC__DEBUG, 0, "Misc", "\t%i => %s", i, sep->arg[i]);
  638. i++;
  639. }
  640. }
  641. }
  642. #define INI_IGNORE(c) (c == '\n' || c == '\r' || c == '#')
  643. static bool INIGoToSection(FILE *f, const char *section) {
  644. size_t size = strlen(section) + 3;
  645. char line[256], *buf, *tmp;
  646. bool found = false;
  647. if ((buf = (char *)malloc(size)) == NULL) {
  648. fprintf(stderr, "%s: %u: Unable to allocate %zu bytes\n", __FUNCTION__, __LINE__, size);
  649. return false;
  650. }
  651. sprintf(buf, "[%s]", section);
  652. while (fgets(line, sizeof(line), f) != NULL) {
  653. if (INI_IGNORE(line[0]))
  654. continue;
  655. if (line[0] == '[') {
  656. if ((tmp = strstr(line, "\n")) != NULL)
  657. *tmp = '\0';
  658. if ((tmp = strstr(line, "\r")) != NULL)
  659. *tmp = '\0';
  660. if (strcasecmp(buf, line) == 0) {
  661. found = true;
  662. break;
  663. }
  664. }
  665. }
  666. free(buf);
  667. return found;
  668. }
  669. static char * INIFindValue(FILE *f, const char *section, const char *property) {
  670. char line[256], *key, *val;
  671. if (section != NULL && !INIGoToSection(f, section))
  672. return NULL;
  673. while (fgets(line, sizeof(line), f) != NULL) {
  674. if (INI_IGNORE(line[0]))
  675. continue;
  676. if (section != NULL && line[0] == '[')
  677. return NULL;
  678. if ((key = strtok(line, "=")) == NULL)
  679. continue;
  680. if (strcasecmp(key, property) == 0) {
  681. val = strtok(NULL, "\n\r");
  682. if (val == NULL)
  683. return NULL;
  684. return strdup(val);
  685. }
  686. }
  687. return NULL;
  688. }
  689. bool INIReadInt(FILE *f, const char *section, const char *property, int *out) {
  690. char *value;
  691. rewind(f);
  692. if ((value = INIFindValue(f, section, property)) == NULL)
  693. return false;
  694. if (!IsNumber(value)) {
  695. free(value);
  696. return false;
  697. }
  698. *out = atoi(value);
  699. free(value);
  700. return true;
  701. }
  702. bool INIReadBool(FILE *f, const char *section, const char *property, bool *out) {
  703. char *value;
  704. rewind(f);
  705. if ((value = INIFindValue(f, section, property)) == NULL)
  706. return false;
  707. *out = (strcasecmp(value, "1") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "on") == 0 || strcasecmp(value, "yes") == 0);
  708. free(value);
  709. return true;
  710. }
  711. string GetDeviceName(string device) {
  712. if (device == "chemistry_table")
  713. device = "Chemistry Table";
  714. else if (device == "work_desk")
  715. device = "Engraved Desk";
  716. else if (device == "forge")
  717. device = "Forge";
  718. else if (device == "stove and keg")
  719. device = "Stove & Keg";
  720. else if (device == "sewing_table")
  721. device = "Sewing Table & Mannequin";
  722. else if (device == "woodworking_table")
  723. device = "Woodworking Table";
  724. else if (device == "work_bench")
  725. device = "Work Bench";
  726. else if (device == "crafting_intro_anvil")
  727. device = "Mender's Anvil";
  728. return device;
  729. }
  730. int32 GetDeviceID(string device) {
  731. if (device == "Chemistry Table")
  732. return 3;
  733. else if (device == "Engraved Desk")
  734. return 4;
  735. else if (device == "Forge")
  736. return 2;
  737. else if (device == "Stove & Keg")
  738. return 7;
  739. else if (device == "Sewing Table & Mannequin")
  740. return 1;
  741. else if (device == "Woodworking Table")
  742. return 6;
  743. else if (device == "Work Bench")
  744. return 5;
  745. else if (device == "Mender's Anvil")
  746. return 0xFFFFFFFF;
  747. return 0;
  748. }
  749. int16 GetItemPacketType(int32 version) {
  750. int16 item_version;
  751. if (version >= 64707)
  752. item_version = 0x5CFE;
  753. else if (version >= 63119)
  754. item_version = 0x56FE;
  755. else if (version >= 60024)
  756. item_version = 0x51FE;
  757. else if (version >= 57107)
  758. item_version = 0x4CFE;
  759. else if (version >= 57048)
  760. item_version = 0x48FE;
  761. else if (version >= 1199)
  762. item_version = 0x44FE;
  763. else if (version >= 1195)
  764. item_version = 0x40FE;
  765. else if (version >= 1193)
  766. item_version = 0x3FFE;
  767. else if (version >= 1190)
  768. item_version = 0x3EFE;
  769. else if (version >= 1188)
  770. item_version = 0x3DFE;
  771. else if (version >= 1096)
  772. item_version = 0x35FE;
  773. else if (version >= 1027)
  774. item_version = 0x31FE;
  775. else if (version >= 1008)
  776. item_version = 0x2CFE;
  777. else if (version >= 927)
  778. item_version = 0x23FE;
  779. else if (version >= 893)
  780. item_version = 0x22FE;
  781. else if (version >= 860)
  782. item_version = 0x20FE;
  783. else if (version > 546)
  784. item_version = 0x1CFE;
  785. else
  786. item_version = 0;
  787. return item_version;
  788. }
  789. #ifndef PATCHER
  790. int16 GetOpcodeVersion(int16 version) {
  791. int16 ret = version;
  792. int16 version1 = 0;
  793. int16 version2 = 0;
  794. map<int16, int16>::iterator itr;
  795. for (itr = EQOpcodeVersions.begin(); itr != EQOpcodeVersions.end(); itr++) {
  796. version1 = itr->first;
  797. version2 = itr->second;
  798. if (version >= version1 && version <= version2) {
  799. ret = version1;
  800. break;
  801. }
  802. }
  803. return ret;
  804. }
  805. #endif
  806. void SleepMS(int32 milliseconds) {
  807. #if defined(_WIN32)
  808. Sleep(milliseconds);
  809. #else
  810. usleep(milliseconds * 1000);
  811. #endif
  812. }
  813. size_t
  814. strlcpy(char *dst, const char *src, size_t size) {
  815. char *d = dst;
  816. const char *s = src;
  817. size_t n = size;
  818. if (n != 0 && --n != 0) {
  819. do {
  820. if ((*d++ = *s++) == 0)
  821. break;
  822. } while (--n != 0);
  823. }
  824. if (n == 0) {
  825. if (size != 0)
  826. *d = '\0';
  827. while (*s++)
  828. ;
  829. }
  830. return(s - src - 1);
  831. }
  832. float short_to_float(const ushort x) { // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
  833. const uint32 e = (x & 0x7C00) >> 10; // exponent
  834. const uint32 m = (x & 0x03FF) << 13; // mantissa
  835. const uint32 v = as_uint((float)m) >> 23; // evil log2 bit hack to count leading zeros in denormalized format
  836. return as_float((x & 0x8000) << 16 | (e != 0) * ((e + 112) << 23 | m) | ((e == 0) & (m != 0)) * ((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000))); // sign : normalized : denormalized
  837. }
  838. uint32 float_to_int(const float x) { // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
  839. const uint32 b = as_uint(x) + 0x00001000; // round-to-nearest-even: add last bit after truncated mantissa
  840. const uint32 e = (b & 0x7F800000) >> 23; // exponent
  841. const uint32 m = b & 0x007FFFFF; // mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
  842. return (b & 0x80000000) >> 16 | (e > 112)* ((((e - 112) << 10) & 0x7C00) | m >> 13) | ((e < 113) & (e > 101))* ((((0x007FF000 + m) >> (125 - e)) + 1) >> 1) | (e > 143) * 0x7FFF; // sign : normalized : denormalized : saturate
  843. }
  844. uint32 as_uint(const float x) {
  845. return *(uint32*)&x;
  846. }
  847. float as_float(const uint32 x) {
  848. return *(float*)&x;
  849. }
  850. // Function to get the current timestamp in milliseconds
  851. int64 getCurrentTimestamp() {
  852. auto now = std::chrono::steady_clock::now();
  853. auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
  854. return duration.count();
  855. }
  856. std::tuple<int, int, int, int> convertTimestampDuration(int64 total_seconds) {
  857. std::chrono::milliseconds duration(total_seconds);
  858. // Convert to days, hours, minutes, and seconds
  859. auto days = std::chrono::duration_cast<std::chrono::duration<int, std::ratio<86400000>>>(duration);
  860. duration -= days;
  861. auto hours = std::chrono::duration_cast<std::chrono::hours>(duration);
  862. duration -= hours;
  863. auto minutes = std::chrono::duration_cast<std::chrono::minutes>(duration);
  864. duration -= minutes;
  865. auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
  866. // Return the result as a tuple
  867. return std::make_tuple(days.count(), hours.count(), minutes.count(), seconds.count());
  868. }