9
3

MiscFunctions.cpp 21 KB

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