|
Atrinik Client 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00067 #include <global.h> 00068 00073 void BookCmd(unsigned char *data, int len) 00074 { 00075 sound_play_effect("book.ogg", 100); 00076 book_load((char *) data, len); 00077 } 00078 00084 void SetupCmd(char *buf, int len) 00085 { 00086 int s; 00087 char *cmd, *param; 00088 00089 server_files_clear_update(); 00090 LOG(llevInfo, "Get SetupCmd:: %s\n", buf); 00091 00092 for (s = 0; ;) 00093 { 00094 while (s < len && buf[s] == ' ') 00095 { 00096 s++; 00097 } 00098 00099 if (s >= len) 00100 { 00101 break; 00102 } 00103 00104 cmd = &buf[s]; 00105 00106 while (s < len && buf[s] != ' ') 00107 { 00108 s++; 00109 } 00110 00111 if (s >= len) 00112 { 00113 break; 00114 } 00115 00116 buf[s++] = '\0'; 00117 00118 if (s >= len) 00119 { 00120 break; 00121 } 00122 00123 while (s < len && buf[s] == ' ') 00124 { 00125 s++; 00126 } 00127 00128 if (s >= len) 00129 { 00130 break; 00131 } 00132 00133 param = &buf[s]; 00134 00135 while (s < len && buf[s] != ' ') 00136 { 00137 s++; 00138 } 00139 00140 buf[s++] = '\0'; 00141 00142 while (s < len && buf[s] == ' ') 00143 { 00144 s++; 00145 } 00146 00147 if (!strcmp(cmd, "sound")) 00148 { 00149 if (!strcmp(param, "FALSE")) 00150 { 00151 } 00152 } 00153 else if (!strcmp(cmd, "mapsize")) 00154 { 00155 } 00156 else if (!strcmp(cmd, "map2cmd")) 00157 { 00158 } 00159 else if (!strcmp(cmd, "darkness")) 00160 { 00161 } 00162 else if (!strcmp(cmd, "facecache")) 00163 { 00164 } 00165 else if (server_files_parse_setup(cmd, param)) 00166 { 00167 } 00168 else 00169 { 00170 LOG(llevBug, "Got setup for a command we don't understand: %s %s\n", cmd, param); 00171 } 00172 } 00173 00174 if (GameStatus != GAME_STATUS_PLAY) 00175 { 00176 GameStatus = GAME_STATUS_REQUEST_FILES; 00177 } 00178 } 00179 00184 void AddMeFail(unsigned char *data, int len) 00185 { 00186 (void) data; 00187 (void) len; 00188 00189 LOG(llevInfo, "addme_failed received.\n"); 00190 GameStatus = GAME_STATUS_START; 00191 } 00192 00196 void AddMeSuccess(unsigned char *data, int len) 00197 { 00198 (void) data; 00199 (void) len; 00200 00201 LOG(llevInfo, "addme_success received.\n"); 00202 } 00203 00208 void AnimCmd(unsigned char *data, int len) 00209 { 00210 short anum; 00211 int i, j; 00212 00213 anum = GetShort_String(data); 00214 00215 if (anum < 0) 00216 { 00217 fprintf(stderr, "AnimCmd: animation number invalid: %d\n", anum); 00218 return; 00219 } 00220 00221 animations[anum].flags = *(data + 2); 00222 animations[anum].facings = *(data + 3); 00223 animations[anum].num_animations = (len - 4) / 2; 00224 00225 if (animations[anum].num_animations < 1) 00226 { 00227 LOG(llevDebug, "AnimCmd: num animations invalid: %d\n", animations[anum].num_animations); 00228 return; 00229 } 00230 00231 if (animations[anum].facings > 1) 00232 { 00233 animations[anum].frame = animations[anum].num_animations / animations[anum].facings; 00234 } 00235 else 00236 { 00237 animations[anum].frame = animations[anum].num_animations; 00238 } 00239 00240 animations[anum].faces = malloc(sizeof(uint16) * animations[anum].num_animations); 00241 00242 for (i = 4, j = 0; i < len; i += 2, j++) 00243 { 00244 animations[anum].faces[j] = GetShort_String(data + i); 00245 request_face(animations[anum].faces[j]); 00246 } 00247 00248 if (j != animations[anum].num_animations) 00249 { 00250 LOG(llevDebug, "Calculated animations does not equal stored animations? (%d != %d)\n", j, animations[anum].num_animations); 00251 } 00252 } 00253 00258 void ImageCmd(unsigned char *data, int len) 00259 { 00260 int pnum, plen; 00261 char buf[2048]; 00262 FILE *stream; 00263 00264 pnum = GetInt_String(data); 00265 plen = GetInt_String(data + 4); 00266 00267 if (len < 8 || (len - 8) != plen) 00268 { 00269 LOG(llevBug, "ImageCmd(): Lengths don't compare (%d, %d)\n", (len - 8), plen); 00270 return; 00271 } 00272 00273 /* Save picture to cache and load it to FaceList */ 00274 sprintf(buf, DIRECTORY_CACHE"/%s", FaceList[pnum].name); 00275 LOG(llevInfo, "ImageFromServer: %s\n", FaceList[pnum].name); 00276 00277 if ((stream = fopen_wrapper(buf, "wb+")) != NULL) 00278 { 00279 fwrite((char *) data + 8, 1, plen, stream); 00280 fclose(stream); 00281 } 00282 00283 FaceList[pnum].sprite = sprite_tryload_file(buf, 0, NULL); 00284 map_udate_flag = 2; 00285 map_redraw_flag = 1; 00286 book_redraw(); 00287 } 00288 00293 void SkillRdyCmd(char *data, int len) 00294 { 00295 size_t type, id; 00296 00297 (void) len; 00298 00299 strncpy(cpl.skill_name, data, sizeof(cpl.skill_name) - 1); 00300 cpl.skill_name[sizeof(cpl.skill_name) - 1] = '\0'; 00301 cpl.skill = NULL; 00302 00303 if (skill_find(cpl.skill_name, &type, &id)) 00304 { 00305 skill_entry_struct *skill = skill_get(type, id); 00306 00307 if (skill->known) 00308 { 00309 cpl.skill = skill; 00310 } 00311 } 00312 00313 WIDGET_REDRAW_ALL(SKILL_EXP_ID); 00314 } 00315 00319 void DrawInfoCmd(unsigned char *data) 00320 { 00321 char color[COLOR_BUF]; 00322 int pos = 0; 00323 00324 GetString_String(data, &pos, color, sizeof(color)); 00325 draw_info(color, (char *) data + pos); 00326 } 00327 00333 void DrawInfoCmd2(unsigned char *data, int len) 00334 { 00335 int flags; 00336 char color[COLOR_BUF], buf[20048], *tmp = NULL; 00337 int pos = 0; 00338 00339 flags = (int) GetShort_String(data); 00340 pos += 2; 00341 00342 GetString_String(data, &pos, color, sizeof(color)); 00343 len -= pos; 00344 00345 data += pos; 00346 00347 if (len >= 0) 00348 { 00349 if (len > 20000) 00350 { 00351 len = 20000; 00352 } 00353 00354 if (setting_get_int(OPT_CAT_GENERAL, OPT_CHAT_TIMESTAMPS) && (flags & NDI_PLAYER)) 00355 { 00356 time_t now = time(NULL); 00357 char timebuf[32], *format; 00358 struct tm *tm = localtime(&now); 00359 size_t timelen; 00360 00361 switch (setting_get_int(OPT_CAT_GENERAL, OPT_CHAT_TIMESTAMPS)) 00362 { 00363 /* HH:MM */ 00364 case 1: 00365 default: 00366 format = "%H:%M"; 00367 break; 00368 00369 /* HH:MM:SS */ 00370 case 2: 00371 format = "%H:%M:%S"; 00372 break; 00373 00374 /* H:MM AM/PM */ 00375 case 3: 00376 format = "%I:%M %p"; 00377 break; 00378 00379 /* H:MM:SS AM/PM */ 00380 case 4: 00381 format = "%I:%M:%S %p"; 00382 break; 00383 } 00384 00385 timelen = strftime(timebuf, sizeof(timebuf), format, tm); 00386 00387 if (timelen == 0) 00388 { 00389 strncpy(buf, (char *) data, len); 00390 } 00391 else 00392 { 00393 len += (int) timelen + 4; 00394 snprintf(buf, len, "[%s] %s", timebuf, (char *) data); 00395 } 00396 } 00397 else 00398 { 00399 strncpy(buf, (char *) data, len); 00400 } 00401 00402 buf[len] = '\0'; 00403 } 00404 else 00405 { 00406 buf[0] = '\0'; 00407 } 00408 00409 if (buf[0] && (flags & (NDI_PLAYER | NDI_SAY | NDI_SHOUT | NDI_TELL | NDI_EMOTE))) 00410 { 00411 tmp = strchr((char *) data, ' '); 00412 00413 if (tmp) 00414 { 00415 *tmp = '\0'; 00416 } 00417 } 00418 00419 /* We have communication input */ 00420 if (tmp) 00421 { 00422 if ((flags & NDI_SAY) && ignore_check((char *) data, "say")) 00423 { 00424 return; 00425 } 00426 00427 if ((flags & NDI_SHOUT) && ignore_check((char *) data, "shout")) 00428 { 00429 return; 00430 } 00431 00432 if ((flags & NDI_TELL) && ignore_check((char *) data, "tell")) 00433 { 00434 return; 00435 } 00436 00437 if ((flags & NDI_EMOTE) && ignore_check((char *) data, "emote")) 00438 { 00439 return; 00440 } 00441 00442 /* Save last incoming tell for client-sided /reply */ 00443 if (flags & NDI_TELL) 00444 { 00445 strncpy(cpl.player_reply, (char *) data, sizeof(cpl.player_reply)); 00446 } 00447 } 00448 00449 if (flags & NDI_ANIM) 00450 { 00451 strncpy(msg_anim.message, buf, sizeof(msg_anim.message) - 1); 00452 msg_anim.tick = LastTick; 00453 strncpy(msg_anim.color, color, sizeof(msg_anim.color) - 1); 00454 msg_anim.color[sizeof(msg_anim.color) - 1] = '\0'; 00455 } 00456 00457 draw_info_flags(color, flags, buf); 00458 } 00459 00464 void TargetObject(unsigned char *data, int len) 00465 { 00466 int pos = 0; 00467 00468 (void) len; 00469 00470 cpl.target_mode = data[pos++]; 00471 00472 if (cpl.target_mode) 00473 { 00474 sound_play_effect("weapon_attack.ogg", 100); 00475 } 00476 else 00477 { 00478 sound_play_effect("weapon_hold.ogg", 100); 00479 } 00480 00481 cpl.target_code = data[pos++]; 00482 GetString_String(data, &pos, cpl.target_color, sizeof(cpl.target_color)); 00483 GetString_String(data, &pos, cpl.target_name, sizeof(cpl.target_name)); 00484 00485 map_udate_flag = 2; 00486 map_redraw_flag = 1; 00487 } 00488 00493 void StatsCmd(unsigned char *data, int len) 00494 { 00495 int i = 0; 00496 int c, temp; 00497 00498 while (i < len) 00499 { 00500 c = data[i++]; 00501 00502 if (c >= CS_STAT_PROT_START && c <= CS_STAT_PROT_END) 00503 { 00504 cpl.stats.protection[c - CS_STAT_PROT_START] = (sint16) *(((signed char *) data) + i++); 00505 WIDGET_REDRAW_ALL(RESIST_ID); 00506 } 00507 else 00508 { 00509 switch (c) 00510 { 00511 case CS_STAT_TARGET_HP: 00512 cpl.target_hp = (int)*(data + i++); 00513 break; 00514 00515 case CS_STAT_REG_HP: 00516 cpl.gen_hp = abs(GetShort_String(data + i)) / 10.0f; 00517 i += 2; 00518 WIDGET_REDRAW_ALL(REGEN_ID); 00519 break; 00520 00521 case CS_STAT_REG_MANA: 00522 cpl.gen_sp = abs(GetShort_String(data + i)) / 10.0f; 00523 i += 2; 00524 WIDGET_REDRAW_ALL(REGEN_ID); 00525 break; 00526 00527 case CS_STAT_REG_GRACE: 00528 cpl.gen_grace = abs(GetShort_String(data + i)) / 10.0f; 00529 i += 2; 00530 WIDGET_REDRAW_ALL(REGEN_ID); 00531 break; 00532 00533 case CS_STAT_HP: 00534 temp = GetInt_String(data + i); 00535 00536 if (temp < cpl.stats.hp && cpl.stats.food) 00537 { 00538 cpl.warn_hp = 1; 00539 00540 if (cpl.stats.maxhp / 12 <= cpl.stats.hp - temp) 00541 { 00542 cpl.warn_hp = 2; 00543 } 00544 } 00545 00546 cpl.stats.hp = temp; 00547 i += 4; 00548 WIDGET_REDRAW_ALL(STATS_ID); 00549 break; 00550 00551 case CS_STAT_MAXHP: 00552 cpl.stats.maxhp = GetInt_String(data + i); 00553 i += 4; 00554 WIDGET_REDRAW_ALL(STATS_ID); 00555 break; 00556 00557 case CS_STAT_SP: 00558 cpl.stats.sp = GetShort_String(data + i); 00559 i += 2; 00560 WIDGET_REDRAW_ALL(STATS_ID); 00561 break; 00562 00563 case CS_STAT_MAXSP: 00564 cpl.stats.maxsp = GetShort_String(data + i); 00565 i += 2; 00566 WIDGET_REDRAW_ALL(STATS_ID); 00567 break; 00568 00569 case CS_STAT_GRACE: 00570 cpl.stats.grace = GetShort_String(data + i); 00571 i += 2; 00572 WIDGET_REDRAW_ALL(STATS_ID); 00573 break; 00574 00575 case CS_STAT_MAXGRACE: 00576 cpl.stats.maxgrace = GetShort_String(data + i); 00577 i += 2; 00578 WIDGET_REDRAW_ALL(STATS_ID); 00579 break; 00580 00581 case CS_STAT_STR: 00582 temp = (int) *(data + i++); 00583 00584 if (temp > cpl.stats.Str) 00585 { 00586 cpl.warn_statup = 1; 00587 } 00588 else 00589 { 00590 cpl.warn_statdown = 1; 00591 } 00592 00593 cpl.stats.Str = temp; 00594 WIDGET_REDRAW_ALL(STATS_ID); 00595 break; 00596 00597 case CS_STAT_INT: 00598 temp = (int) *(data + i++); 00599 00600 if (temp > cpl.stats.Int) 00601 { 00602 cpl.warn_statup = 1; 00603 } 00604 else 00605 { 00606 cpl.warn_statdown = 1; 00607 } 00608 00609 cpl.stats.Int = temp; 00610 WIDGET_REDRAW_ALL(STATS_ID); 00611 break; 00612 00613 case CS_STAT_POW: 00614 temp = (int) *(data + i++); 00615 00616 if (temp > cpl.stats.Pow) 00617 { 00618 cpl.warn_statup = 1; 00619 } 00620 else 00621 { 00622 cpl.warn_statdown = 1; 00623 } 00624 00625 cpl.stats.Pow = temp; 00626 WIDGET_REDRAW_ALL(STATS_ID); 00627 break; 00628 00629 case CS_STAT_WIS: 00630 temp = (int) *(data + i++); 00631 00632 if (temp > cpl.stats.Wis) 00633 { 00634 cpl.warn_statup = 1; 00635 } 00636 else 00637 { 00638 cpl.warn_statdown = 1; 00639 } 00640 00641 cpl.stats.Wis = temp; 00642 WIDGET_REDRAW_ALL(STATS_ID); 00643 break; 00644 00645 case CS_STAT_DEX: 00646 temp = (int) *(data + i++); 00647 00648 if (temp > cpl.stats.Dex) 00649 { 00650 cpl.warn_statup = 1; 00651 } 00652 else 00653 { 00654 cpl.warn_statdown = 1; 00655 } 00656 00657 cpl.stats.Dex = temp; 00658 WIDGET_REDRAW_ALL(STATS_ID); 00659 break; 00660 00661 case CS_STAT_CON: 00662 temp = (int) *(data + i++); 00663 00664 if (temp > cpl.stats.Con) 00665 { 00666 cpl.warn_statup = 1; 00667 } 00668 else 00669 { 00670 cpl.warn_statdown = 1; 00671 } 00672 00673 cpl.stats.Con = temp; 00674 WIDGET_REDRAW_ALL(STATS_ID); 00675 break; 00676 00677 case CS_STAT_CHA: 00678 temp = (int) *(data + i++); 00679 00680 if (temp > cpl.stats.Cha) 00681 { 00682 cpl.warn_statup = 1; 00683 } 00684 else 00685 { 00686 cpl.warn_statdown = 1; 00687 } 00688 00689 cpl.stats.Cha = temp; 00690 WIDGET_REDRAW_ALL(STATS_ID); 00691 break; 00692 00693 case CS_STAT_EXP: 00694 cpl.stats.exp = GetInt64_String(data + i); 00695 i += 8; 00696 WIDGET_REDRAW_ALL(MAIN_LVL_ID); 00697 break; 00698 00699 case CS_STAT_LEVEL: 00700 cpl.stats.level = (char) *(data + i++); 00701 WIDGET_REDRAW_ALL(MAIN_LVL_ID); 00702 break; 00703 00704 case CS_STAT_WC: 00705 cpl.stats.wc = GetShort_String(data + i); 00706 i += 2; 00707 break; 00708 00709 case CS_STAT_AC: 00710 cpl.stats.ac = GetShort_String(data + i); 00711 i += 2; 00712 break; 00713 00714 case CS_STAT_DAM: 00715 cpl.stats.dam = GetShort_String(data + i); 00716 i += 2; 00717 break; 00718 00719 case CS_STAT_SPEED: 00720 cpl.stats.speed = GetInt_String(data + i); 00721 i += 4; 00722 break; 00723 00724 case CS_STAT_FOOD: 00725 cpl.stats.food = GetShort_String(data + i); 00726 i += 2; 00727 WIDGET_REDRAW_ALL(STATS_ID); 00728 break; 00729 00730 case CS_STAT_WEAP_SP: 00731 cpl.stats.weapon_sp = (int) *(data + i++); 00732 break; 00733 00734 case CS_STAT_FLAGS: 00735 cpl.stats.flags = GetShort_String(data + i); 00736 i += 2; 00737 break; 00738 00739 case CS_STAT_WEIGHT_LIM: 00740 set_weight_limit(GetInt_String(data + i)); 00741 i += 4; 00742 break; 00743 00744 case CS_STAT_ACTION_TIME: 00745 cpl.action_timer = abs(GetInt_String(data + i)) / 1000.0f; 00746 i += 4; 00747 WIDGET_REDRAW_ALL(SKILL_EXP_ID); 00748 break; 00749 00750 case CS_STAT_SKILLEXP_AGILITY: 00751 case CS_STAT_SKILLEXP_PERSONAL: 00752 case CS_STAT_SKILLEXP_MENTAL: 00753 case CS_STAT_SKILLEXP_PHYSIQUE: 00754 case CS_STAT_SKILLEXP_MAGIC: 00755 case CS_STAT_SKILLEXP_WISDOM: 00756 cpl.stats.skill_exp[(c - CS_STAT_SKILLEXP_START) / 2] = GetInt64_String(data + i); 00757 i += 8; 00758 WIDGET_REDRAW_ALL(SKILL_LVL_ID); 00759 break; 00760 00761 case CS_STAT_SKILLEXP_AGLEVEL: 00762 case CS_STAT_SKILLEXP_PELEVEL: 00763 case CS_STAT_SKILLEXP_MELEVEL: 00764 case CS_STAT_SKILLEXP_PHLEVEL: 00765 case CS_STAT_SKILLEXP_MALEVEL: 00766 case CS_STAT_SKILLEXP_WILEVEL: 00767 cpl.stats.skill_level[(c - CS_STAT_SKILLEXP_START - 1) / 2] = (sint16)*(data + i++); 00768 WIDGET_REDRAW_ALL(SKILL_LVL_ID); 00769 break; 00770 00771 case CS_STAT_RANGE: 00772 { 00773 int rlen = data[i++]; 00774 00775 strncpy(cpl.range, (const char *) data + i, rlen); 00776 cpl.range[rlen] = '\0'; 00777 i += rlen; 00778 break; 00779 } 00780 00781 case CS_STAT_EXT_TITLE: 00782 { 00783 int rlen = data[i++]; 00784 00785 strncpy(cpl.ext_title, (const char *) data + i, rlen); 00786 cpl.ext_title[rlen] = '\0'; 00787 i += rlen; 00788 00789 if (strstr(cpl.ext_title, "[WIZ]")) 00790 { 00791 cpl.dm = 1; 00792 } 00793 else 00794 { 00795 cpl.dm = 0; 00796 } 00797 00798 break; 00799 } 00800 00801 case CS_STAT_RANGED_DAM: 00802 cpl.stats.ranged_dam = GetShort_String(data + i); 00803 i += 2; 00804 break; 00805 00806 case CS_STAT_RANGED_WC: 00807 cpl.stats.ranged_wc = GetShort_String(data + i); 00808 i += 2; 00809 break; 00810 00811 case CS_STAT_RANGED_WS: 00812 cpl.stats.ranged_ws = GetInt_String(data + i); 00813 i += 4; 00814 break; 00815 00816 default: 00817 fprintf(stderr, "Unknown stat number %d\n", c); 00818 } 00819 } 00820 } 00821 00822 if (i > len) 00823 { 00824 fprintf(stderr, "Got stats overflow, processed %d bytes out of %d\n", i, len); 00825 } 00826 } 00827 00831 void PreParseInfoStat(char *cmd) 00832 { 00833 /* Find input name */ 00834 if (strstr(cmd, "What is your name?")) 00835 { 00836 LOG(llevInfo, "Login: Enter name\n"); 00837 cpl.name[0] = '\0'; 00838 cpl.password[0] = '\0'; 00839 GameStatus = GAME_STATUS_NAME; 00840 } 00841 00842 if (strstr(cmd, "What is your password?")) 00843 { 00844 LOG(llevInfo, "Login: Enter password\n"); 00845 GameStatus = GAME_STATUS_PSWD; 00846 } 00847 00848 if (strstr(cmd, "Please type your password again.")) 00849 { 00850 LOG(llevInfo, "Login: Enter verify password\n"); 00851 GameStatus = GAME_STATUS_VERIFYPSWD; 00852 } 00853 00854 if (GameStatus >= GAME_STATUS_NAME && GameStatus <= GAME_STATUS_VERIFYPSWD) 00855 { 00856 text_input_open(64); 00857 } 00858 } 00859 00863 void handle_query(char *data) 00864 { 00865 char *buf, *cp; 00866 00867 buf = strchr(data, ' '); 00868 00869 if (buf) 00870 { 00871 buf++; 00872 } 00873 00874 if (buf) 00875 { 00876 cp = buf; 00877 00878 while ((buf = strchr(buf, '\n')) != NULL) 00879 { 00880 *buf++ = '\0'; 00881 LOG(llevInfo, "Received query string: %s\n", cp); 00882 PreParseInfoStat(cp); 00883 cp = buf; 00884 } 00885 } 00886 } 00887 00891 void send_reply(char *text) 00892 { 00893 char buf[HUGE_BUF]; 00894 00895 snprintf(buf, sizeof(buf), "reply %s", text); 00896 cs_write_string(buf, strlen(buf)); 00897 } 00898 00904 void PlayerCmd(unsigned char *data, int len) 00905 { 00906 char name[MAX_BUF]; 00907 int tag, weight, face, i = 0, nlen; 00908 00909 GameStatus = GAME_STATUS_PLAY; 00910 text_input_string_end_flag = 0; 00911 tag = GetInt_String(data); 00912 i += 4; 00913 weight = GetInt_String(data + i); 00914 i += 4; 00915 face = GetInt_String(data + i); 00916 request_face(face); 00917 i += 4; 00918 nlen = data[i++]; 00919 memcpy(name, (const char *) data + i, nlen); 00920 00921 name[nlen] = '\0'; 00922 i += nlen; 00923 00924 if (i != len) 00925 { 00926 fprintf(stderr, "PlayerCmd: lengths do not match (%d!=%d)\n", len, i); 00927 } 00928 00929 new_player(tag, weight, (short) face); 00930 map_udate_flag = 2; 00931 map_redraw_flag = 1; 00932 00933 ignore_list_load(); 00934 } 00935 00940 void ItemXCmd(unsigned char *data, int len) 00941 { 00942 int weight, loc, tag, face, flags, pos = 0, nlen, anim, nrof, dmode; 00943 uint8 itype, stype, item_qua, item_con, item_skill, item_level; 00944 uint8 animspeed, direction = 0; 00945 char name[MAX_BUF]; 00946 00947 map_udate_flag = 2; 00948 itype = stype = item_qua = item_con = item_skill = item_level = 0; 00949 00950 dmode = GetInt_String(data); 00951 pos += 4; 00952 00953 loc = GetInt_String(data+pos); 00954 00955 if (dmode >= 0) 00956 { 00957 object_remove_inventory(object_find(loc)); 00958 } 00959 00960 /* send item flag */ 00961 if (dmode == -4) 00962 { 00963 /* and redirect it to our invisible sack */ 00964 if (loc == cpl.container_tag) 00965 { 00966 loc = -1; 00967 } 00968 } 00969 /* container flag! */ 00970 else if (dmode == -1) 00971 { 00972 /* we catch the REAL container tag */ 00973 cpl.container_tag = loc; 00974 object_remove_inventory(object_find(-1)); 00975 00976 /* if this happens, we want to close the container */ 00977 if (loc == -1) 00978 { 00979 cpl.container_tag = -998; 00980 return; 00981 } 00982 00983 /* and redirect it to our invisible sack */ 00984 loc = -1; 00985 } 00986 00987 pos += 4; 00988 00989 if (pos == len && loc != -1) 00990 { 00991 LOG(llevBug, "ItemXCmd(): Got location with no other data\n"); 00992 } 00993 else 00994 { 00995 while (pos < len) 00996 { 00997 tag = GetInt_String(data + pos); 00998 pos += 4; 00999 flags = GetInt_String(data + pos); 01000 pos += 4; 01001 weight = GetInt_String(data + pos); 01002 pos += 4; 01003 face = GetInt_String(data + pos); 01004 pos += 4; 01005 request_face(face); 01006 direction = data[pos++]; 01007 01008 if (loc) 01009 { 01010 itype = data[pos++]; 01011 stype = data[pos++]; 01012 item_qua = data[pos++]; 01013 item_con = data[pos++]; 01014 item_level = data[pos++]; 01015 item_skill = data[pos++]; 01016 } 01017 01018 nlen = data[pos++]; 01019 memcpy(name, (char *) data + pos, nlen); 01020 pos += nlen; 01021 name[nlen] = '\0'; 01022 anim = GetShort_String(data + pos); 01023 pos += 2; 01024 animspeed = data[pos++]; 01025 nrof = GetInt_String(data + pos); 01026 pos += 4; 01027 update_object(tag, loc, name, weight, face, flags, anim, animspeed, nrof, itype, stype, item_qua, item_con, item_skill, item_level, direction, 0); 01028 } 01029 01030 if (pos > len) 01031 { 01032 LOG(llevBug, "ItemXCmd(): Overread buffer: %d > %d\n", pos, len); 01033 } 01034 } 01035 01036 map_udate_flag = 2; 01037 } 01038 01043 void ItemYCmd(unsigned char *data, int len) 01044 { 01045 int weight, loc, tag, face, flags, pos = 0, nlen, anim, nrof, dmode; 01046 uint8 itype, stype, item_qua, item_con, item_skill, item_level; 01047 uint8 animspeed, direction = 0; 01048 char name[MAX_BUF]; 01049 01050 map_udate_flag = 2; 01051 itype = stype = item_qua = item_con = item_skill = item_level = 0; 01052 01053 dmode = GetInt_String(data); 01054 pos += 4; 01055 01056 loc = GetInt_String(data + pos); 01057 01058 if (dmode >= 0) 01059 { 01060 object_remove_inventory(object_find(loc)); 01061 } 01062 01063 /* send item flag */ 01064 if (dmode == -4) 01065 { 01066 /* and redirect it to our invisible sack */ 01067 if (loc == cpl.container_tag) 01068 { 01069 loc = -1; 01070 } 01071 } 01072 /* container flag! */ 01073 else if (dmode == -1) 01074 { 01075 /* we catch the REAL container tag */ 01076 cpl.container_tag = loc; 01077 object_remove_inventory(object_find(-1)); 01078 01079 /* if this happens, we want to close the container */ 01080 if (loc == -1) 01081 { 01082 cpl.container_tag = -998; 01083 return; 01084 } 01085 01086 /* and redirect it to our invisible sack */ 01087 loc = -1; 01088 } 01089 01090 01091 pos += 4; 01092 01093 if (pos == len && loc != -1) 01094 { 01095 /* server sends no clean command to clear below window */ 01096 } 01097 else 01098 { 01099 while (pos < len) 01100 { 01101 tag = GetInt_String(data + pos); 01102 pos += 4; 01103 flags = GetInt_String(data + pos); 01104 pos += 4; 01105 weight = GetInt_String(data + pos); 01106 pos += 4; 01107 face = GetInt_String(data + pos); 01108 pos += 4; 01109 request_face(face); 01110 direction = data[pos++]; 01111 01112 if (loc) 01113 { 01114 itype = data[pos++]; 01115 stype = data[pos++]; 01116 item_qua = data[pos++]; 01117 item_con = data[pos++]; 01118 item_level = data[pos++]; 01119 item_skill = data[pos++]; 01120 } 01121 01122 nlen = data[pos++]; 01123 memcpy(name, (char *) data + pos, nlen); 01124 pos += nlen; 01125 name[nlen] = '\0'; 01126 anim = GetShort_String(data + pos); 01127 pos += 2; 01128 animspeed = data[pos++]; 01129 nrof = GetInt_String(data + pos); 01130 pos += 4; 01131 update_object(tag, loc, name, weight, face, flags, anim, animspeed, nrof, itype, stype, item_qua, item_con, item_skill, item_level, direction, 1); 01132 } 01133 01134 if (pos > len) 01135 { 01136 LOG(llevBug, "ItemYCmd(): Overread buffer: %d > %d\n", pos, len); 01137 } 01138 } 01139 01140 map_udate_flag = 2; 01141 } 01142 01147 void UpdateItemCmd(unsigned char *data, int len) 01148 { 01149 int weight, loc, tag, face, sendflags, flags, pos = 0, nlen, anim, nrof; 01150 uint8 direction; 01151 char name[MAX_BUF]; 01152 object *ip, *env = NULL; 01153 uint8 animspeed; 01154 01155 map_udate_flag = 2; 01156 sendflags = GetShort_String(data); 01157 pos += 2; 01158 tag = GetInt_String(data + pos); 01159 pos += 4; 01160 ip = object_find(tag); 01161 01162 if (!ip) 01163 { 01164 return; 01165 } 01166 01167 *name = '\0'; 01168 loc = ip->env ? ip->env->tag : 0; 01169 weight = (int) (ip->weight * 1000); 01170 face = ip->face; 01171 request_face(face); 01172 flags = ip->flags; 01173 anim = ip->animation_id; 01174 animspeed = (uint8) ip->anim_speed; 01175 nrof = ip->nrof; 01176 direction = ip->direction; 01177 01178 if (sendflags & UPD_LOCATION) 01179 { 01180 loc = GetInt_String(data + pos); 01181 env = object_find(loc); 01182 01183 if (!env) 01184 { 01185 fprintf(stderr, "UpdateItemCmd: unknown object tag (%d) for new location\n", loc); 01186 } 01187 01188 pos += 4; 01189 } 01190 01191 if (sendflags & UPD_FLAGS) 01192 { 01193 flags = GetInt_String(data + pos); 01194 pos += 4; 01195 } 01196 01197 if (sendflags & UPD_WEIGHT) 01198 { 01199 weight = GetInt_String(data + pos); 01200 pos += 4; 01201 } 01202 01203 if (sendflags & UPD_FACE) 01204 { 01205 face = GetInt_String(data + pos); 01206 request_face(face); 01207 pos += 4; 01208 } 01209 01210 if (sendflags & UPD_DIRECTION) 01211 { 01212 direction = data[pos++]; 01213 } 01214 01215 if (sendflags & UPD_NAME) 01216 { 01217 nlen = data[pos++]; 01218 memcpy(name, (char *) data + pos, nlen); 01219 pos += nlen; 01220 name[nlen] = '\0'; 01221 } 01222 01223 if (pos > len) 01224 { 01225 fprintf(stderr, "UpdateItemCmd: Overread buffer: %d > %d\n", pos, len); 01226 return; 01227 } 01228 01229 if (sendflags & UPD_ANIM) 01230 { 01231 anim = GetShort_String(data + pos); 01232 pos += 2; 01233 } 01234 01235 if (sendflags & UPD_ANIMSPEED) 01236 { 01237 animspeed = data[pos++]; 01238 } 01239 01240 if (sendflags & UPD_NROF) 01241 { 01242 nrof = GetInt_String(data + pos); 01243 pos += 4; 01244 } 01245 01246 update_object(tag, loc, name, weight, face, flags, anim, animspeed, nrof, 254, 254, 254, 254, 254, 254, direction, 0); 01247 map_udate_flag = 2; 01248 } 01249 01254 void DeleteItem(unsigned char *data, int len) 01255 { 01256 int pos = 0,tag; 01257 01258 while (pos < len) 01259 { 01260 tag = GetInt_String(data); 01261 pos += 4; 01262 delete_object(tag); 01263 } 01264 01265 if (pos > len) 01266 { 01267 fprintf(stderr, "ItemCmd: Overread buffer: %d > %d\n", pos, len); 01268 } 01269 01270 map_udate_flag = 2; 01271 } 01272 01276 void DeleteInventory(unsigned char *data) 01277 { 01278 int tag; 01279 01280 tag = atoi((const char *) data); 01281 01282 if (tag < 0) 01283 { 01284 fprintf(stderr, "DeleteInventory: Invalid tag: %d\n", tag); 01285 return; 01286 } 01287 01288 object_remove_inventory(object_find(tag)); 01289 map_udate_flag = 2; 01290 } 01291 01294 static void map_play_footstep() 01295 { 01296 static int step = 0; 01297 static uint32 tick = 0; 01298 01299 if (LastTick - tick > 125) 01300 { 01301 step++; 01302 01303 if (step % 2) 01304 { 01305 sound_play_effect("step1.ogg", 100); 01306 } 01307 else 01308 { 01309 step = 0; 01310 sound_play_effect("step2.ogg", 100); 01311 } 01312 01313 tick = LastTick; 01314 } 01315 } 01316 01321 void MapStatsCmd(unsigned char *data, int len) 01322 { 01323 int pos = 0; 01324 char buf[HUGE_BUF]; 01325 uint8 type; 01326 01327 /* Loop, trying to find data. */ 01328 while (pos < len) 01329 { 01330 /* Get the type of this command... */ 01331 type = (uint8) (data[pos++]); 01332 01333 /* Change map name. */ 01334 if (type == CMD_MAPSTATS_NAME) 01335 { 01336 strncpy(buf, (const char *) (data + pos), sizeof(buf) - 1); 01337 buf[sizeof(buf) - 1] = '\0'; 01338 pos += strlen(buf) + 1; 01339 update_map_name(buf); 01340 } 01341 /* Change map music. */ 01342 else if (type == CMD_MAPSTATS_MUSIC) 01343 { 01344 strncpy(buf, (const char *) (data + pos), sizeof(buf) - 1); 01345 buf[sizeof(buf) - 1] = '\0'; 01346 pos += strlen(buf) + 1; 01347 update_map_bg_music(buf); 01348 } 01349 /* Change map weather. */ 01350 else if (type == CMD_MAPSTATS_WEATHER) 01351 { 01352 strncpy(buf, (const char *) (data + pos), sizeof(buf) - 1); 01353 buf[sizeof(buf) - 1] = '\0'; 01354 pos += strlen(buf) + 1; 01355 update_map_weather(buf); 01356 } 01357 } 01358 } 01359 01364 void Map2Cmd(unsigned char *data, int len) 01365 { 01366 static int mx = 0, my = 0; 01367 int mask, x, y, pos = 0; 01368 int mapstat; 01369 int xpos, ypos; 01370 int layer, ext_flags; 01371 uint8 num_layers; 01372 01373 mapstat = (uint8) (data[pos++]); 01374 01375 if (mapstat != MAP_UPDATE_CMD_SAME) 01376 { 01377 char mapname[HUGE_BUF], bg_music[HUGE_BUF], weather[MAX_BUF]; 01378 01379 strncpy(mapname, (const char *) (data + pos), sizeof(mapname) - 1); 01380 pos += strlen(mapname) + 1; 01381 strncpy(bg_music, (const char *) (data + pos), sizeof(bg_music) - 1); 01382 pos += strlen(bg_music) + 1; 01383 strncpy(weather, (const char *) (data + pos), sizeof(weather) - 1); 01384 pos += strlen(weather) + 1; 01385 01386 if (mapstat == MAP_UPDATE_CMD_NEW) 01387 { 01388 int map_w, map_h; 01389 01390 map_w = (uint8) (data[pos++]); 01391 map_h = (uint8) (data[pos++]); 01392 xpos = (uint8) (data[pos++]); 01393 ypos = (uint8) (data[pos++]); 01394 mx = xpos; 01395 my = ypos; 01396 object_remove_inventory(object_find(0)); 01397 init_map_data(map_w, map_h, xpos, ypos); 01398 } 01399 else 01400 { 01401 int xoff, yoff; 01402 01403 mapstat = (sint8) (data[pos++]); 01404 xoff = (sint8) (data[pos++]); 01405 yoff = (sint8) (data[pos++]); 01406 xpos = (uint8) (data[pos++]); 01407 ypos = (uint8) (data[pos++]); 01408 mx = xpos; 01409 my = ypos; 01410 object_remove_inventory(object_find(0)); 01411 display_mapscroll(xoff, yoff); 01412 01413 map_play_footstep(); 01414 } 01415 01416 update_map_name(mapname); 01417 update_map_bg_music(bg_music); 01418 update_map_weather(weather); 01419 } 01420 else 01421 { 01422 xpos = (uint8) (data[pos++]); 01423 ypos = (uint8) (data[pos++]); 01424 01425 /* we have moved */ 01426 if ((xpos - mx || ypos - my)) 01427 { 01428 object_remove_inventory(object_find(0)); 01429 cpl.win_below_slot = 0; 01430 01431 display_mapscroll(xpos - mx, ypos - my); 01432 map_play_footstep(); 01433 } 01434 01435 mx = xpos; 01436 my = ypos; 01437 } 01438 01439 MapData.posx = xpos; 01440 MapData.posy = ypos; 01441 01442 while (pos < len) 01443 { 01444 mask = GetShort_String(data + pos); 01445 pos += 2; 01446 x = (mask >> 11) & 0x1f; 01447 y = (mask >> 6) & 0x1f; 01448 01449 /* Clear the whole cell? */ 01450 if (mask & MAP2_MASK_CLEAR) 01451 { 01452 map_clear_cell(x, y); 01453 continue; 01454 } 01455 01456 /* Do we have darkness information? */ 01457 if (mask & MAP2_MASK_DARKNESS) 01458 { 01459 map_set_darkness(x, y, (uint8) (data[pos++])); 01460 } 01461 01462 num_layers = data[pos++]; 01463 01464 /* Go through all the layers on this tile. */ 01465 for (layer = 0; layer < num_layers; layer++) 01466 { 01467 uint8 type = data[pos++]; 01468 01469 /* Clear this layer. */ 01470 if (type == MAP2_LAYER_CLEAR) 01471 { 01472 map_set_data(x, y, data[pos++], 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, 0, 0); 01473 } 01474 /* We have some data. */ 01475 else 01476 { 01477 sint16 face = GetShort_String(data + pos), height = 0, zoom = 0, align = 0, rotate = 0; 01478 uint8 flags, obj_flags, quick_pos = 0, probe = 0, draw_double = 0, alpha = 0, infravision = 0; 01479 char player_name[64], player_color[COLOR_BUF]; 01480 01481 player_name[0] = '\0'; 01482 player_color[0] = '\0'; 01483 01484 pos += 2; 01485 /* Request the face. */ 01486 request_face(face); 01487 /* Object flags. */ 01488 obj_flags = data[pos++]; 01489 /* Flags of this layer. */ 01490 flags = data[pos++]; 01491 01492 /* Multi-arch? */ 01493 if (flags & MAP2_FLAG_MULTI) 01494 { 01495 quick_pos = data[pos++]; 01496 } 01497 01498 /* Player name? */ 01499 if (flags & MAP2_FLAG_NAME) 01500 { 01501 GetString_String(data, &pos, player_name, sizeof(player_name)); 01502 GetString_String(data, &pos, player_color, sizeof(player_color)); 01503 } 01504 01505 /* Target's HP? */ 01506 if (flags & MAP2_FLAG_PROBE) 01507 { 01508 probe = data[pos++]; 01509 } 01510 01511 /* Z position? */ 01512 if (flags & MAP2_FLAG_HEIGHT) 01513 { 01514 height = GetShort_String(data + pos); 01515 pos += 2; 01516 } 01517 01518 /* Zoom? */ 01519 if (flags & MAP2_FLAG_ZOOM) 01520 { 01521 zoom = GetShort_String(data + pos); 01522 pos += 2; 01523 } 01524 01525 /* Align? */ 01526 if (flags & MAP2_FLAG_ALIGN) 01527 { 01528 align = GetShort_String(data + pos); 01529 pos += 2; 01530 } 01531 01532 /* Double? */ 01533 if (flags & MAP2_FLAG_DOUBLE) 01534 { 01535 draw_double = 1; 01536 } 01537 01538 if (flags & MAP2_FLAG_MORE) 01539 { 01540 uint32 flags2 = GetInt_String(data + pos); 01541 01542 pos += 4; 01543 01544 if (flags2 & MAP2_FLAG2_ALPHA) 01545 { 01546 alpha = data[pos++]; 01547 } 01548 01549 if (flags2 & MAP2_FLAG2_ROTATE) 01550 { 01551 rotate = GetShort_String(data + pos); 01552 pos += 2; 01553 } 01554 01555 if (flags2 & MAP2_FLAG2_INFRAVISION) 01556 { 01557 infravision = 1; 01558 } 01559 } 01560 01561 /* Set the data we figured out. */ 01562 map_set_data(x, y, type, face, quick_pos, obj_flags, player_name, player_color, height, probe, zoom, align, draw_double, alpha, rotate, infravision); 01563 } 01564 } 01565 01566 /* Get tile flags. */ 01567 ext_flags = data[pos++]; 01568 01569 /* Animation? */ 01570 if (ext_flags & MAP2_FLAG_EXT_ANIM) 01571 { 01572 uint8 anim_type; 01573 sint16 anim_value; 01574 01575 anim_type = data[pos++]; 01576 anim_value = GetShort_String(data + pos); 01577 pos += 2; 01578 01579 add_anim(anim_type, xpos + x, ypos + y, anim_value); 01580 } 01581 } 01582 01583 adjust_tile_stretch(); 01584 map_udate_flag = 2; 01585 map_redraw_flag = 1; 01586 } 01587 01590 void MagicMapCmd(unsigned char *data, int len) 01591 { 01592 (void) data; 01593 (void) len; 01594 } 01595 01599 void VersionCmd(char *data) 01600 { 01601 (void) data; 01602 } 01603 01607 void SendVersion() 01608 { 01609 char buf[MAX_BUF]; 01610 01611 snprintf(buf, sizeof(buf), "version %d %s", SOCKET_VERSION, PACKAGE_NAME); 01612 cs_write_string(buf, strlen(buf)); 01613 } 01614 01619 void RequestFile(int idx) 01620 { 01621 char buf[MAX_BUF]; 01622 01623 sprintf(buf, "rf %d", idx); 01624 cs_write_string(buf, strlen(buf)); 01625 } 01626 01630 void SendAddMe() 01631 { 01632 cs_write_string("addme", 5); 01633 } 01634 01638 void NewCharCmd() 01639 { 01640 GameStatus = GAME_STATUS_NEW_CHAR; 01641 } 01642 01648 void DataCmd(unsigned char *data, int len) 01649 { 01650 uint8 data_type; 01651 unsigned long len_ucomp; 01652 unsigned char *dest; 01653 01654 data_type = *data++; 01655 len_ucomp = GetInt_String(data); 01656 data += 4; 01657 len -= 5; 01658 /* Allocate large enough buffer to hold the uncompressed file. */ 01659 dest = malloc(len_ucomp); 01660 01661 LOG(llevInfo, "DataCmd(): Uncompressing file #%d (len: %d, uncompressed len: %lu)\n", data_type, len, len_ucomp); 01662 uncompress((Bytef *) dest, (uLongf *) &len_ucomp, (const Bytef *) data, (uLong) len); 01663 data = dest; 01664 len = len_ucomp; 01665 server_file_save(data_type, data, len); 01666 free(dest); 01667 } 01668 01673 void ShopCmd(unsigned char *data, int len) 01674 { 01675 (void) data; 01676 (void) len; 01677 } 01678 01685 void QuestListCmd(unsigned char *data, int len) 01686 { 01687 sound_play_effect("book.ogg", 100); 01688 01689 data += 4; 01690 book_load((char *) data, len - 4); 01691 } 01692 01698 void ReadyCmd(unsigned char *data, int len) 01699 { 01700 int tag; 01701 uint8 type; 01702 01703 (void) len; 01704 01705 type = data[0]; 01706 tag = GetInt_String(data + 1); 01707 01708 if (type == READY_OBJ_ARROW) 01709 { 01710 fire_mode_tab[FIRE_MODE_BOW].amun = tag; 01711 } 01712 else if (type == READY_OBJ_THROW) 01713 { 01714 fire_mode_tab[FIRE_MODE_THROW].item = tag; 01715 } 01716 }
1.7.4