|
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 00044 #include <global.h> 00045 00047 Client_Player cpl; 00048 00050 ClientSocket csocket; 00051 00053 typedef void (*CmdProc)(unsigned char *, int len); 00054 00055 struct CmdMapping 00056 { 00057 const char *cmdname; 00058 void (*cmdproc)(unsigned char *, int); 00059 enum CmdFormat cmdformat; 00060 }; 00061 00062 enum 00063 { 00064 BINARY_CMD_COMC = 1, 00065 BINARY_CMD_MAP2, 00066 BINARY_CMD_DRAWINFO, 00067 BINARY_CMD_DRAWINFO2, 00068 BINARY_CMD_FILE_UPD, 00069 BINARY_CMD_ITEMX, 00070 BINARY_CMD_SOUND, 00071 BINARY_CMD_TARGET, 00072 BINARY_CMD_UPITEM, 00073 BINARY_CMD_DELITEM, 00074 BINARY_CMD_STATS, 00075 BINARY_CMD_IMAGE, 00076 BINARY_CMD_FACE1, 00077 BINARY_CMD_ANIM, 00078 BINARY_CMD_SKILLRDY, 00079 BINARY_CMD_PLAYER, 00080 BINARY_CMD_MAPSTATS, 00081 BINARY_CMD_SPELL_LIST, 00082 BINARY_CMD_SKILL_LIST, 00083 BINARY_CMD_CLEAR, 00084 BINARY_CMD_ADDME_SUC, 00085 BINARY_CMD_ADDME_FAIL, 00086 BINARY_CMD_VERSION, 00087 BINARY_CMD_BYE, 00088 BINARY_CMD_SETUP, 00089 BINARY_CMD_QUERY, 00090 BINARY_CMD_DATA, 00091 BINARY_CMD_NEW_CHAR, 00092 BINARY_CMD_ITEMY, 00093 BINARY_CMD_BOOK, 00094 BINARY_CMD_PARTY, 00095 BINARY_CMD_QUICKSLOT, 00096 BINARY_CMD_SHOP, 00097 BINARY_CMD_QLIST, 00098 BINARY_CMD_REGION_MAP, 00099 BINARY_CMD_READY, 00100 BINARY_CMD_KEEPALIVE, 00101 /* last entry */ 00102 BINAR_CMD 00103 }; 00104 00106 struct CmdMapping commands[] = 00107 { 00108 /* Order of this table doesn't make a difference. I tried to sort 00109 * of cluster the related stuff together. */ 00110 {"comc", CompleteCmd, SHORT_INT}, 00111 {"map2", Map2Cmd, MIXED}, 00112 {"drawinfo", (CmdProc) DrawInfoCmd, ASCII}, 00113 {"drawinfo2", (CmdProc) DrawInfoCmd2, ASCII}, 00114 {"request_upd", cmd_request_update, ASCII}, 00115 {"itemx", ItemXCmd, MIXED}, 00116 {"sound", SoundCmd, ASCII}, 00117 {"to", TargetObject, ASCII}, 00118 {"upditem", UpdateItemCmd, MIXED}, 00119 {"delitem", DeleteItem, INT_ARRAY}, 00120 {"stats", StatsCmd, STATS}, 00121 {"image", ImageCmd, ASCII}, 00122 {"face1", NULL, SHORT_ARRAY}, 00123 {"anim", AnimCmd, SHORT_ARRAY}, 00124 {"skill_rdy", (CmdProc) SkillRdyCmd, ASCII}, 00125 {"player", PlayerCmd, MIXED}, 00126 {"mapstats", MapStatsCmd, ASCII}, 00127 {"splist", (CmdProc) SpelllistCmd, ASCII}, 00128 {"sklist", (CmdProc) SkilllistCmd, ASCII}, 00129 {"clr", NULL, ASCII}, 00130 {"addme_success", AddMeSuccess, NODATA}, 00131 {"addme_failed", AddMeFail, NODATA}, 00132 {"version", (CmdProc) VersionCmd, NODATA}, 00133 {"goodbye", NULL, NODATA}, 00134 {"setup", (CmdProc) SetupCmd, ASCII}, 00135 {"query", (CmdProc) handle_query, ASCII}, 00136 {"data", (CmdProc) DataCmd, MIXED}, 00137 {"new_char", (CmdProc) NewCharCmd, NODATA}, 00138 {"itemy", ItemYCmd, MIXED}, 00139 {"book", BookCmd, ASCII}, 00140 {"pt", PartyCmd, ASCII}, 00141 {"qs", QuickSlotCmd, ASCII}, 00142 {"shop", ShopCmd, ASCII}, 00143 {"qlist", QuestListCmd, ASCII}, 00144 {"region_map", RegionMapCmd, ASCII}, 00145 {"rd", ReadyCmd, INT_ARRAY}, 00146 {"ka", NULL, NODATA}, 00147 00148 /* Unused! */ 00149 {"magicmap", MagicMapCmd, NODATA}, 00150 {"delinv", (CmdProc) DeleteInventory, NODATA}, 00151 }; 00152 00156 void DoClient() 00157 { 00158 command_buffer *cmd; 00159 00160 /* Handle all enqueued commands */ 00161 while ((cmd = get_next_input_command())) 00162 { 00163 uint8 *data = cmd->data, *dest = NULL; 00164 size_t len = cmd->len; 00165 00166 /* Binary command #0 is reserved for compressed data packets, so 00167 * attempt to uncompress it. */ 00168 if (data[0] == 0) 00169 { 00170 unsigned long ucomp_len; 00171 00172 /* Get original length so we can allocate a large enough 00173 * buffer. */ 00174 ucomp_len = GetInt_String(data + 1) + 1; 00175 /* Allocate the buffer. */ 00176 dest = malloc(ucomp_len); 00177 00178 if (!dest) 00179 { 00180 LOG(llevError, "DoClient(): Out of memory.\n"); 00181 } 00182 00183 uncompress((Bytef *) dest, (uLongf *) &ucomp_len, (const Bytef *) data + 5, (uLong) len - 5); 00184 data = dest; 00185 len = ucomp_len; 00186 data[len] = '\0'; 00187 } 00188 00189 if (!data[0] || data[0] > BINAR_CMD) 00190 { 00191 LOG(llevBug, "Bad command from server (%d)\n", data[0]); 00192 } 00193 else 00194 { 00195 script_trigger_event(commands[data[0] - 1].cmdname, data + 1, len - 1, commands[data[0] - 1].cmdformat); 00196 commands[data[0] - 1].cmdproc(data + 1, len - 1); 00197 } 00198 00199 /* Should we free the data because it was allocated by previous 00200 * uncompression? */ 00201 if (dest) 00202 { 00203 free(dest); 00204 } 00205 00206 command_buffer_free(cmd); 00207 } 00208 } 00209 00213 void SockList_Init(SockList *sl) 00214 { 00215 sl->len = 0; 00216 sl->buf = NULL; 00217 } 00218 00223 void SockList_AddChar(SockList *sl, char c) 00224 { 00225 sl->buf[sl->len] = c; 00226 sl->len++; 00227 } 00228 00233 void SockList_AddShort(SockList *sl, uint16 data) 00234 { 00235 sl->buf[sl->len++] = (data >> 8) & 0xff; 00236 sl->buf[sl->len++] = data & 0xff; 00237 } 00238 00243 void SockList_AddInt(SockList *sl, uint32 data) 00244 { 00245 sl->buf[sl->len++] = (data >> 24) & 0xff; 00246 sl->buf[sl->len++] = (data >> 16) & 0xff; 00247 sl->buf[sl->len++] = (data >> 8) & 0xff; 00248 sl->buf[sl->len++] = data & 0xff; 00249 } 00250 00255 void SockList_AddString(SockList *sl, char *data) 00256 { 00257 char c; 00258 00259 while ((c = *data++)) 00260 { 00261 sl->buf[sl->len] = c; 00262 sl->len++; 00263 } 00264 } 00265 00270 void SockList_AddStringTerminated(SockList *sl, char *data) 00271 { 00272 char c; 00273 00274 while ((c = *data++)) 00275 { 00276 sl->buf[sl->len] = c; 00277 sl->len++; 00278 } 00279 00280 sl->buf[sl->len] = c; 00281 sl->len++; 00282 } 00283 00288 int GetInt_String(const unsigned char *data) 00289 { 00290 return ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]); 00291 } 00292 00297 sint64 GetInt64_String(const unsigned char *data) 00298 { 00299 #ifdef WIN32 00300 return (((sint64) data[0] << 56) + ((sint64) data[1] << 48) + ((sint64) data[2] << 40) + ((sint64) data[3] << 32) + ((sint64) data[4] << 24) + ((sint64) data[5] << 16) + ((sint64) data[6] << 8) + (sint64) data[7]); 00301 #else 00302 return (((uint64) data[0] << 56) + ((uint64) data[1] << 48) + ((uint64) data[2] << 40) + ((uint64) data[3] << 32) + ((uint64) data[4] << 24) + (data[5] << 16) + (data[6] << 8) + data[7]); 00303 #endif 00304 } 00305 00310 short GetShort_String(const unsigned char *data) 00311 { 00312 return ((data[0] << 8) + data[1]); 00313 } 00314 00322 char *GetString_String(uint8 *data, int *pos, char *dest, size_t dest_size) 00323 { 00324 size_t i = 0; 00325 char c; 00326 00327 while ((c = (char) (data[(*pos)++]))) 00328 { 00329 if (i < dest_size - 1) 00330 { 00331 dest[i++] = c; 00332 } 00333 } 00334 00335 dest[i] = '\0'; 00336 return dest; 00337 } 00338 00345 int cs_write_string(char *buf, size_t len) 00346 { 00347 SockList sl; 00348 00349 sl.len = (int) len; 00350 sl.buf = (unsigned char *) buf; 00351 00352 return send_socklist(sl); 00353 } 00354 00358 void check_animation_status(int anum) 00359 { 00360 /* Check if it has been loaded. */ 00361 if (animations[anum].loaded) 00362 { 00363 return; 00364 } 00365 00366 /* Mark this animation as loaded. */ 00367 animations[anum].loaded = 1; 00368 /* Same as server sends it */ 00369 AnimCmd((unsigned char *) anim_table[anum].anim_cmd, anim_table[anum].len); 00370 }
1.7.4