root/src/char/inter.c @ 23

Revision 1, 20.2 kB (checked in by jinshiro, 17 years ago)
Line 
1// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
2// For more information, see LICENCE in the main folder
3
4#include "../common/db.h"
5#include "../common/mmo.h"
6#include "../common/socket.h"
7#include "../common/timer.h"
8#include "../common/malloc.h"
9#include "../common/lock.h"
10#include "../common/showmsg.h"
11#include "../common/strlib.h"
12#include "char.h"
13#include "inter.h"
14#include "int_party.h"
15#include "int_guild.h"
16#include "int_status.h"
17#include "int_storage.h"
18#include "int_pet.h"
19#include "int_homun.h"
20
21#include <stdio.h>
22#include <string.h>
23#include <stdlib.h>
24
25#define WISDATA_TTL (60*1000)   // Existence time of Wisp/page data (60 seconds)
26                                // that is the waiting time of answers of all map-servers
27#define WISDELLIST_MAX 256      // Number of elements of Wisp/page data deletion list
28
29char accreg_txt[1024] = "save/accreg.txt";
30#ifndef TXT_SQL_CONVERT
31char inter_log_filename[1024] = "log/inter.log";
32char main_chat_nick[16] = "Main";
33
34static DBMap* accreg_db = NULL; // int account_id -> struct accreg*
35
36unsigned int party_share_level = 10;
37
38// sending packet list
39// NOTE: This variable ain't used at all! And it's confusing.. where do I add that the length of packet 0x2b07 is 10? x.x [Skotlex]
40int inter_send_packet_length[]={
41        -1,-1,27,-1, -1, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3000-0x300f
42        -1, 7, 0, 0,  0, 0, 0, 0, -1,11, 0, 0,  0, 0,  0, 0,
43        35,-1,11,15, 34,29, 7,-1,  0, 0, 0, 0,  0, 0,  0, 0,
44        10,-1,15, 0, 79,19, 7,-1,  0,-1,-1,-1, 14,67,186,-1,
45         9, 9,-1, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,
46         0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,
47         0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,
48         0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,
49        11,-1, 7, 3, 36, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,
50};
51// recv. packet list
52int inter_recv_packet_length[]={
53        -1,-1, 7,-1, -1,13,36, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3000-0x300f
54         6,-1, 0, 0,  0, 0, 0, 0, 10,-1, 0, 0,  0, 0,  0, 0, //0x3010-0x301f
55        -1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0,  0, 0,  0, 0, //0x3020-0x302f
56        -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, //0x3030-0x303f
57         5, 9, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3040-0x304f
58         0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3050-0x305f
59         0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3060-0x306f
60         0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3070-0x307f
61        48,14,-1, 6,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3080-0x308f
62        -1,10,-1, 6,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3090-0x309f  Homunculus packets [albator]
63};
64
65struct WisData {
66        int id, fd, count, len;
67        unsigned long tick;
68        unsigned char src[24], dst[24], msg[1024];
69};
70static DBMap* wis_db = NULL; // int wis_id -> struct WisData*
71static int wis_dellist[WISDELLIST_MAX], wis_delnum;
72
73
74//--------------------------------------------------------
75
76// ƒAƒJƒEƒ“ƒg•ϐ”‚ð•¶Žš—ñ‚Ö•ÏŠ·
77int inter_accreg_tostr(char *str, struct accreg *reg) {
78        int j;
79        char *p = str;
80
81        p += sprintf(p, "%d\t", reg->account_id);
82        for(j = 0; j < reg->reg_num; j++) {
83                p += sprintf(p,"%s,%s ", reg->reg[j].str, reg->reg[j].value);
84        }
85
86        return 0;
87}
88#endif //TXT_SQL_CONVERT
89// ƒAƒJƒEƒ“ƒg•ϐ”‚ð•¶Žš—ñ‚©‚ç•ÏŠ·
90int inter_accreg_fromstr(const char *str, struct accreg *reg) {
91        int j, n;
92        const char *p = str;
93
94        if (sscanf(p, "%d\t%n", &reg->account_id, &n ) != 1 || reg->account_id <= 0)
95                return 1;
96
97        for(j = 0, p += n; j < ACCOUNT_REG_NUM; j++, p += n) {
98                if (sscanf(p, "%[^,],%[^ ] %n", reg->reg[j].str, reg->reg[j].value, &n) != 2) 
99                        break;
100        }
101        reg->reg_num = j;
102
103        return 0;
104}
105#ifndef TXT_SQL_CONVERT
106// ƒAƒJƒEƒ“ƒg•ϐ”‚̓ǂݍž‚Ý
107int inter_accreg_init(void) {
108        char line[8192];
109        FILE *fp;
110        int c = 0;
111        struct accreg *reg;
112
113        accreg_db = idb_alloc(DB_OPT_RELEASE_DATA);
114
115        if( (fp = fopen(accreg_txt, "r")) == NULL)
116                return 1;
117        while(fgets(line, sizeof(line), fp))
118        {
119                reg = (struct accreg*)aCalloc(sizeof(struct accreg), 1);
120                if (reg == NULL) {
121                        ShowFatalError("inter: accreg: out of memory!\n");
122                        exit(EXIT_FAILURE);
123                }
124                if (inter_accreg_fromstr(line, reg) == 0 && reg->account_id > 0) {
125                        idb_put(accreg_db, reg->account_id, reg);
126                } else {
127                        ShowError("inter: accreg: broken data [%s] line %d\n", accreg_txt, c);
128                        aFree(reg);
129                }
130                c++;
131        }
132        fclose(fp);
133
134        return 0;
135}
136
137// ƒAƒJƒEƒ“ƒg•ϐ”‚̃Z[ƒu—p
138int inter_accreg_save_sub(DBKey key, void *data, va_list ap) {
139        char line[8192];
140        FILE *fp;
141        struct accreg *reg = (struct accreg *)data;
142
143        if (reg->reg_num > 0) {
144                inter_accreg_tostr(line,reg);
145                fp = va_arg(ap, FILE *);
146                fprintf(fp, "%s\n", line);
147        }
148
149        return 0;
150}
151
152// ƒAƒJƒEƒ“ƒg•ϐ”‚̃Z[ƒu
153int inter_accreg_save(void) {
154        FILE *fp;
155        int lock;
156
157        if ((fp = lock_fopen(accreg_txt,&lock)) == NULL) {
158                ShowError("int_accreg: can't write [%s] !!! data is lost !!!\n", accreg_txt);
159                return 1;
160        }
161        accreg_db->foreach(accreg_db, inter_accreg_save_sub,fp);
162        lock_fclose(fp, accreg_txt, &lock);
163
164        return 0;
165}
166
167//--------------------------------------------------------
168#endif //TXT_SQL_CONVERT
169/*==========================================
170 * Ý’èƒtƒ@ƒCƒ‹‚ð“ǂݍž‚Þ
171 *------------------------------------------*/
172static int inter_config_read(const char *cfgName) {
173        char line[1024], w1[1024], w2[1024];
174        FILE *fp;
175
176        fp = fopen(cfgName, "r");
177        if (fp == NULL) {
178                ShowError("file not found: %s\n", cfgName);
179                return 1;
180        }
181        while(fgets(line, sizeof(line), fp))
182        {
183                if (line[0] == '/' && line[1] == '/')
184                        continue;
185
186                if (sscanf(line,"%[^:]: %[^\r\n]", w1, w2) != 2)
187                        continue;
188
189                if (strcmpi(w1, "storage_txt") == 0) {
190                        strncpy(storage_txt, w2, sizeof(storage_txt));
191                } else if (strcmpi(w1, "party_txt") == 0) {
192                        strncpy(party_txt, w2, sizeof(party_txt));
193                } else if (strcmpi(w1, "pet_txt") == 0) {
194                        strncpy(pet_txt, w2, sizeof(pet_txt));
195                } else if (strcmpi(w1, "accreg_txt") == 0) {
196                        strncpy(accreg_txt, w2, sizeof(accreg_txt));
197                } else if (strcmpi(w1, "guild_txt") == 0) {
198                        strncpy(guild_txt, w2, sizeof(guild_txt));
199                } else if (strcmpi(w1, "castle_txt") == 0) {
200                        strncpy(castle_txt, w2, sizeof(castle_txt));
201                } else if (strcmpi(w1, "guild_storage_txt") == 0) {
202                        strncpy(guild_storage_txt, w2, sizeof(guild_storage_txt));
203#ifndef TXT_SQL_CONVERT
204                } else if (strcmpi(w1, "homun_txt") == 0) {
205                        strncpy(homun_txt, w2, sizeof(homun_txt));
206                } else if (strcmpi(w1, "party_share_level") == 0) {
207                        party_share_level = (unsigned int)atof(w2);
208                } else if (strcmpi(w1, "inter_log_filename") == 0) {
209                        strncpy(inter_log_filename, w2, sizeof(inter_log_filename));
210                } else if(strcmpi(w1,"log_inter")==0) {
211                        log_inter = atoi(w2);
212                } else if(strcmpi(w1, "main_chat_nick")==0){    // Main chat nick [LuzZza]
213                        strcpy(main_chat_nick, w2);
214#endif //TXT_SQL_CONVERT
215                } else if (strcmpi(w1, "import") == 0) {
216                        inter_config_read(w2);
217                }
218        }
219        fclose(fp);
220
221        return 0;
222}
223#ifndef TXT_SQL_CONVERT
224// ƒƒO‘‚«o‚µ
225int inter_log(char *fmt,...) {
226        FILE *logfp;
227        va_list ap;
228
229        va_start(ap,fmt);
230        logfp = fopen(inter_log_filename, "a");
231        if (logfp) {
232                vfprintf(logfp, fmt, ap);
233                fclose(logfp);
234        }
235        va_end(ap);
236
237        return 0;
238}
239
240// ƒZ[ƒu
241int inter_save(void) {
242#ifdef ENABLE_SC_SAVING
243        inter_status_save();
244#endif
245        inter_party_save();
246        inter_guild_save();
247        inter_storage_save();
248        inter_guild_storage_save();
249        inter_pet_save();
250        inter_homun_save();
251        inter_accreg_save();
252
253        return 0;
254}
255#endif //TXT_SQL_CONVERT
256// ‰Šú‰»
257int inter_init_txt(const char *file) {
258        inter_config_read(file);
259
260#ifndef TXT_SQL_CONVERT
261        wis_db = idb_alloc(DB_OPT_RELEASE_DATA);
262
263        inter_party_init();
264        inter_guild_init();
265        inter_storage_init();
266        inter_pet_init();
267        inter_homun_init();
268        inter_accreg_init();
269#endif //TXT_SQL_CONVERT
270        return 0;
271}
272#ifndef TXT_SQL_CONVERT
273// finalize
274void inter_final(void) {
275        accreg_db->destroy(accreg_db, NULL);
276        wis_db->destroy(wis_db, NULL);
277
278        inter_party_final();
279        inter_guild_final();
280        inter_storage_final();
281        inter_pet_final();
282        inter_homun_final();
283
284        return;
285}
286
287// ƒ}ƒbƒvƒT[ƒo[Ú‘±
288int inter_mapif_init(int fd) {
289        inter_guild_mapif_init(fd);
290
291        return 0;
292}
293
294//--------------------------------------------------------
295// sended packets to map-server
296
297// GMƒƒbƒZ[ƒW‘—M
298int mapif_GMmessage(unsigned char *mes, int len, unsigned long color, int sfd) {
299        unsigned char buf[2048];
300
301        if (len > 2048) len = 2047; //Make it fit to avoid crashes. [Skotlex]
302        WBUFW(buf,0) = 0x3800;
303        WBUFW(buf,2) = len;
304        WBUFL(buf,4) = color;
305        memcpy(WBUFP(buf,8), mes, len - 8);
306        mapif_sendallwos(sfd, buf, len);
307
308        return 0;
309}
310
311// Wisp/page transmission to one map-server
312int mapif_wis_message2(struct WisData *wd, int fd) {
313        WFIFOHEAD(fd, 56+wd->len);
314        WFIFOW(fd, 0) = 0x3801;
315        WFIFOW(fd, 2) = 56 + wd->len;
316        WFIFOL(fd, 4) = wd->id;
317        memcpy(WFIFOP(fd, 8), wd->src, NAME_LENGTH);
318        memcpy(WFIFOP(fd,32), wd->dst, NAME_LENGTH);
319        memcpy(WFIFOP(fd,56), wd->msg, wd->len);
320        wd->count = 1;
321        WFIFOSET(fd,WFIFOW(fd,2));
322        return 1;
323}
324
325// Wisp/page transmission to all map-server
326int mapif_wis_message(struct WisData *wd) {
327        unsigned char buf[2048];
328        if (wd->len > 2047-56) wd->len = 2047-56; //Force it to fit to avoid crashes. [Skotlex]
329
330        WBUFW(buf, 0) = 0x3801;
331        WBUFW(buf, 2) = 56 + wd->len;
332        WBUFL(buf, 4) = wd->id;
333        memcpy(WBUFP(buf, 8), wd->src, NAME_LENGTH);
334        memcpy(WBUFP(buf,32), wd->dst, NAME_LENGTH);
335        memcpy(WBUFP(buf,56), wd->msg, wd->len);
336        wd->count = mapif_sendall(buf, WBUFW(buf,2));
337
338        return 0;
339}
340
341int mapif_wis_fail(int fd, char *src) {
342        unsigned char buf[27];
343        WBUFW(buf, 0) = 0x3802;
344        memcpy(WBUFP(buf, 2), src, NAME_LENGTH);
345        WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
346        mapif_send(fd, buf, 27);
347        return 0;
348
349}
350
351// Wisp/page transmission result to map-server
352int mapif_wis_end(struct WisData *wd, int flag)
353{
354        unsigned char buf[27];
355
356        WBUFW(buf, 0) = 0x3802;
357        memcpy(WBUFP(buf, 2), wd->src, 24);
358        WBUFB(buf,26) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
359        mapif_send(wd->fd, buf, 27);
360
361        return 0;
362}
363
364// Account registry transfer to map-server
365static void mapif_account_reg(int fd, unsigned char *src)
366{
367        WBUFW(src,0)=0x3804; //NOTE: writing to RFIFO
368        mapif_sendallwos(fd, src, WBUFW(src,2));
369}
370
371// ƒAƒJƒEƒ“ƒg•ϐ”—v‹•ԐM
372int mapif_account_reg_reply(int fd,int account_id, int char_id)
373{
374        struct accreg *reg = (struct accreg*)idb_get(accreg_db,account_id);
375
376        WFIFOHEAD(fd, ACCOUNT_REG_NUM * 288+ 13);
377        WFIFOW(fd,0) = 0x3804;
378        WFIFOL(fd,4) = account_id;
379        WFIFOL(fd,8) = char_id;
380        WFIFOB(fd,12) = 2; //Acc Reg
381        if (reg == NULL) {
382                WFIFOW(fd,2) = 13;
383        } else {
384                int i, p;
385                for (p=13,i = 0; i < reg->reg_num; i++) {
386                        p+= sprintf((char*)WFIFOP(fd,p), "%s", reg->reg[i].str)+1; //We add 1 to consider the '\0' in place.
387                        p+= sprintf((char*)WFIFOP(fd,p), "%s", reg->reg[i].value)+1;
388                }
389                WFIFOW(fd,2)=p;
390        }
391        WFIFOSET(fd,WFIFOW(fd,2));
392        return 0;
393}
394
395//Request to kick char from a certain map server. [Skotlex]
396int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason)
397{
398        if (fd < 0)
399                return -1;
400       
401        WFIFOHEAD(fd, 7);
402        WFIFOW(fd,0) = 0x2b1f;
403        WFIFOL(fd,2) = account_id;
404        WFIFOB(fd,6) = reason;
405        WFIFOSET(fd,7);
406       
407        return 0;
408}
409
410//--------------------------------------------------------
411
412// Existence check of WISP data
413int check_ttl_wisdata_sub(DBKey key, void *data, va_list ap) {
414        unsigned long tick;
415        struct WisData *wd = (struct WisData *)data;
416        tick = va_arg(ap, unsigned long);
417
418        if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX)
419                wis_dellist[wis_delnum++] = wd->id;
420
421        return 0;
422}
423
424int check_ttl_wisdata(void) {
425        unsigned long tick = gettick();
426        int i;
427
428        do {
429                wis_delnum = 0;
430                wis_db->foreach(wis_db, check_ttl_wisdata_sub, tick);
431                for(i = 0; i < wis_delnum; i++) {
432                        struct WisData *wd = (struct WisData*)idb_get(wis_db, wis_dellist[i]);
433                        ShowWarning("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst);
434                        // removed. not send information after a timeout. Just no answer for the player
435                        //mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
436                        idb_remove(wis_db, wd->id);
437                }
438        } while(wis_delnum >= WISDELLIST_MAX);
439
440        return 0;
441}
442
443//--------------------------------------------------------
444// received packets from map-server
445
446// GMƒƒbƒZ[ƒW‘—M
447int mapif_parse_GMmessage(int fd) {
448        RFIFOHEAD(fd);
449        mapif_GMmessage(RFIFOP(fd,8), RFIFOW(fd,2), RFIFOL(fd,4), fd);
450
451        return 0;
452}
453
454static struct WisData* mapif_create_whisper(int fd, char* src, char* dst, char* mes, int meslen)
455{
456        static int wisid = 0;
457        struct WisData* wd = (struct WisData *)aCalloc(sizeof(struct WisData), 1);
458        if (wd == NULL){
459                ShowFatalError("inter: WisRequest: out of memory !\n");
460                return NULL;
461        }
462        wd->id = ++wisid;
463        wd->fd = fd;
464        wd->len= meslen;
465        memcpy(wd->src, src, NAME_LENGTH);
466        memcpy(wd->dst, dst, NAME_LENGTH);
467        memcpy(wd->msg, mes, meslen);
468        wd->tick = gettick();
469        return wd;
470}
471
472// Wisp/page request to send
473int mapif_parse_WisRequest(int fd)
474{
475        struct mmo_charstatus* char_status;
476        struct WisData* wd;
477        char name[NAME_LENGTH];
478        int fd2;
479
480        if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
481                ShowWarning("inter: Wis message size too long.\n");
482                return 0;
483        } else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows...
484                ShowError("inter: Wis message doesn't exist.\n");
485                return 0;
486        }
487
488        safestrncpy(name, (char*)RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
489
490        // search if character exists before to ask all map-servers
491        char_status = search_character_byname(name);
492        if (char_status == NULL)
493                return mapif_wis_fail(fd, (char*)RFIFOP(fd, 4));
494
495        // Character exists.
496        // to be sure of the correct name, rewrite it
497        memset(name, 0, NAME_LENGTH);
498        strncpy(name, char_status->name, NAME_LENGTH);
499        // if source is destination, don't ask other servers.
500        if (strcmp((char*)RFIFOP(fd,4),name) == 0)
501                return mapif_wis_fail(fd, (char*)RFIFOP(fd, 4));
502
503        //Look for online character.
504        fd2 = search_character_online(char_status->account_id, char_status->char_id);
505        if (fd2 >= 0) { //Character online, send whisper.
506                wd = mapif_create_whisper(fd, (char*)RFIFOP(fd, 4), (char*)RFIFOP(fd,28), (char*)RFIFOP(fd,52), RFIFOW(fd,2)-52);
507                if (!wd) return 1;
508                idb_put(wis_db, wd->id, wd);
509                mapif_wis_message2(wd, fd2);
510                return 0;
511        }
512        //Not found.
513        return mapif_wis_fail(fd, (char*)RFIFOP(fd,4));
514}
515
516// Wisp/page transmission result
517int mapif_parse_WisReply(int fd) {
518        int id, flag;
519        struct WisData *wd;
520        RFIFOHEAD(fd);
521        id = RFIFOL(fd,2);
522        flag = RFIFOB(fd,6);
523        wd = (struct WisData*)idb_get(wis_db, id);
524
525        if (wd == NULL)
526                return 0;       // This wisp was probably suppress before, because it was timeout or because of target was found on another map-server
527
528        if ((--wd->count) <= 0 || flag != 1) {
529                mapif_wis_end(wd, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
530                idb_remove(wis_db, id);
531        }
532
533        return 0;
534}
535
536// Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
537int mapif_parse_WisToGM(int fd) {
538        unsigned char buf[2048]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
539
540        ShowDebug("Sent packet back!\n");
541        memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2));
542        WBUFW(buf, 0) = 0x3803;
543        mapif_sendall(buf, RFIFOW(fd,2));
544
545        return 0;
546}
547
548static void* create_accreg(DBKey key, va_list args) {
549        struct accreg *reg;
550        reg = (struct accreg*)aCalloc(sizeof(struct accreg), 1);
551        reg->account_id = key.i;
552        return reg;
553}
554
555// ƒAƒJƒEƒ“ƒg•ϐ”•Û‘¶—v‹
556int mapif_parse_Registry(int fd) {
557        int j, p, len;
558        struct accreg *reg;
559        RFIFOHEAD(fd);
560
561        switch (RFIFOB(fd,12)) {
562                case 3: //Character registry
563                        return char_parse_Registry(RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,13), RFIFOW(fd,2)-13);
564                case 2: //Acc Reg
565                        break;
566                case 1: //Acc Reg2, forward to login
567                        return save_accreg2(RFIFOP(fd,4), RFIFOW(fd,2)-4);
568                default: //Error?
569                        return 1; 
570        }
571        reg = (struct accreg*)idb_ensure(accreg_db, RFIFOL(fd,4), create_accreg);
572
573        for(j=0,p=13;j<ACCOUNT_REG_NUM && p<RFIFOW(fd,2);j++){
574                sscanf((char*)RFIFOP(fd,p), "%31c%n",reg->reg[j].str,&len);
575                reg->reg[j].str[len]='\0';
576                p +=len+1; //+1 to skip the '\0' between strings.
577                sscanf((char*)RFIFOP(fd,p), "%255c%n",reg->reg[j].value,&len);
578                reg->reg[j].value[len]='\0';
579                p +=len+1;
580        }
581        reg->reg_num=j;
582        mapif_account_reg(fd, RFIFOP(fd,0));    // ‘Œ‚ÌMAPƒT[ƒo[‚É‘—M
583
584        return 0;
585}
586
587// Request the value of all registries.
588int mapif_parse_RegistryRequest(int fd)
589{       
590        RFIFOHEAD(fd);
591        //Load Char Registry
592        if (RFIFOB(fd,12))
593                char_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6));
594        //Load Account Registry
595        if (RFIFOB(fd,11))
596                mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6));
597        //Ask Login Server for Account2 values.
598        if (RFIFOB(fd,10))
599                request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6));
600        return 1;
601}
602
603static void mapif_namechange_ack(int fd, int account_id, int char_id, int type, int flag, char *name){
604        WFIFOHEAD(fd, NAME_LENGTH+13);
605        WFIFOW(fd, 0) =0x3806;
606        WFIFOL(fd, 2) =account_id;
607        WFIFOL(fd, 6) =char_id;
608        WFIFOB(fd,10) =type;
609        WFIFOB(fd,11) =flag;
610        memcpy(WFIFOP(fd, 12), name, NAME_LENGTH);
611        WFIFOSET(fd, NAME_LENGTH+13);
612}
613
614int mapif_parse_NameChangeRequest(int fd)
615{
616        int account_id, char_id, type;
617        char* name;
618        int i;
619
620        RFIFOHEAD(fd);
621        account_id = RFIFOL(fd, 2);
622        char_id = RFIFOL(fd, 6);
623        type = RFIFOB(fd, 10);
624        name = (char*)RFIFOP(fd, 11);
625
626        // Check Authorised letters/symbols in the name
627        if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
628                for (i = 0; i < NAME_LENGTH && name[i]; i++)
629                if (strchr(char_name_letters, name[i]) == NULL) {
630                        mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
631                        return 0;
632                }
633        } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
634                for (i = 0; i < NAME_LENGTH && name[i]; i++)
635                if (strchr(char_name_letters, name[i]) != NULL) {
636                        mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
637                        return 0;
638                }
639        }
640        //TODO: type holds the type of object to rename.
641        //If it were a player, it needs to have the guild information and db information
642        //updated here, because changing it on the map won't make it be saved [Skotlex]
643
644        //name allowed.
645        mapif_namechange_ack(fd, account_id, char_id, type, 1, name);
646        return 0;
647}
648
649//--------------------------------------------------------
650
651// map server ‚©‚ç‚̒ʐMi‚PƒpƒPƒbƒg‚̂݉ðÍ‚·‚邱‚Ɓj
652// ƒGƒ‰[‚È‚ç0(false)Aˆ—‚Å‚«‚œ‚È‚ç1A
653// ƒpƒPƒbƒg’·‚ª‘«‚è‚È‚¯‚ê‚Î2‚ð‚©‚Š‚³‚È‚¯‚ê‚΂Ȃç‚È‚¢
654int inter_parse_frommap(int fd) {
655        int cmd, len;
656        RFIFOHEAD(fd);
657        cmd = RFIFOW(fd,0);
658        len = 0;
659
660        // interŽIŠÇŠ‚©‚𒲂ׂé
661        if (cmd < 0x3000 || cmd >= 0x3000 + ARRAYLENGTH(inter_recv_packet_length))
662                return 0;
663       
664        if (inter_recv_packet_length[cmd-0x3000] == 0) //This is necessary, because otherwise we return 2 and the char server will just hang waiting for packets! [Skotlex]
665                return 0;
666
667        // ƒpƒPƒbƒg’·‚𒲂ׂé
668        if ((len = inter_check_length(fd, inter_recv_packet_length[cmd - 0x3000])) == 0)
669                return 2;
670
671        switch(cmd) {
672        case 0x3000: mapif_parse_GMmessage(fd); break;
673        case 0x3001: mapif_parse_WisRequest(fd); break;
674        case 0x3002: mapif_parse_WisReply(fd); break;
675        case 0x3003: mapif_parse_WisToGM(fd); break;
676        case 0x3004: mapif_parse_Registry(fd); break;
677        case 0x3005: mapif_parse_RegistryRequest(fd); break;
678        case 0x3006: mapif_parse_NameChangeRequest(fd); break;
679        default:
680                if (inter_party_parse_frommap(fd))
681                        break;
682                if (inter_guild_parse_frommap(fd))
683                        break;
684                if (inter_storage_parse_frommap(fd))
685                        break;
686                if (inter_pet_parse_frommap(fd))
687                        break;
688                if (inter_homun_parse_frommap(fd))
689                        break;
690                return 0;
691        }
692        RFIFOSKIP(fd, len);
693        return 1;
694}
695
696// RFIFO‚̃pƒPƒbƒg’·Šm”F
697// •K—vƒpƒPƒbƒg’·‚ª‚ ‚ê‚΃pƒPƒbƒg’·A‚Ü‚Ÿ‘«‚è‚È‚¯‚ê‚Î0
698int inter_check_length(int fd, int length) {
699        if (length == -1) {     // ‰Â•σpƒPƒbƒg’·
700                RFIFOHEAD(fd);
701                if (RFIFOREST(fd) < 4)  // ƒpƒPƒbƒg’·‚ª–¢’…
702                        return 0;
703                length = RFIFOW(fd,2);
704        }
705
706        if ((int)RFIFOREST(fd) < length)        // ƒpƒPƒbƒg‚ª–¢’…
707                return 0;
708
709        return length;
710}
711#endif //TXT_SQL_CONVERT
Note: See TracBrowser for help on using the browser.