summaryrefslogtreecommitdiff
path: root/src/map/chrif.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/chrif.cpp')
-rw-r--r--src/map/chrif.cpp1307
1 files changed, 1307 insertions, 0 deletions
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
new file mode 100644
index 0000000..0223e67
--- /dev/null
+++ b/src/map/chrif.cpp
@@ -0,0 +1,1307 @@
+// $Id: chrif.c,v 1.6 2004/09/25 11:39:17 MouseJstr Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef LCCWIN32
+#include <winsock.h>
+#else
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <sys/types.h>
+#include <time.h>
+
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+#include "map.hpp"
+#include "battle.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "intif.hpp"
+#include "npc.hpp"
+#include "pc.hpp"
+#include "../common/nullpo.hpp"
+#include "itemdb.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+static const int packet_len_table[0x20] = {
+ 60, 3, 10, 27, 22, -1, 6, -1, // 2af8-2aff
+ 6, -1, 18, 7, -1, 49, 44, 0, // 2b00-2b07
+ 6, 30, -1, 10, 86, 7, 44, 34, // 2b08-2b0f
+ -1, -1, 10, 6, 11, -1, 0, 0, // 2b10-2b17
+};
+
+int char_fd;
+int srvinfo;
+static char char_ip_str[16];
+static int char_ip;
+static int char_port = 6121;
+static char userid[24], passwd[24];
+static int chrif_state;
+
+// 設定ファイル読み込み関係
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_setuserid (char *id)
+{
+ strncpy (userid, id, sizeof(userid)-1);
+ userid[sizeof(userid)-1] = '\0';
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_setpasswd (char *pwd)
+{
+ strncpy (passwd, pwd, sizeof(passwd)-1);
+ passwd[sizeof(passwd)-1] = '\0';
+}
+
+char *chrif_getpasswd (void)
+{
+ return passwd;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_setip (char *ip)
+{
+ strncpy (char_ip_str, ip, sizeof(char_ip_str)-1);
+ char_ip_str[sizeof(char_ip_str)-1] = '\0';
+ char_ip = inet_addr (char_ip_str);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_setport (int port)
+{
+ char_port = port;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_isconnect (void)
+{
+ return chrif_state == 2;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_save (struct map_session_data *sd)
+{
+ nullpo_retr (-1, sd);
+
+ if (char_fd < 0)
+ return -1;
+
+ pc_makesavestatus (sd);
+
+ WFIFOW (char_fd, 0) = 0x2b01;
+ WFIFOW (char_fd, 2) = sizeof (sd->status) + 12;
+ WFIFOL (char_fd, 4) = sd->bl.id;
+ WFIFOL (char_fd, 8) = sd->char_id;
+ memcpy (WFIFOP (char_fd, 12), &sd->status, sizeof (sd->status));
+ WFIFOSET (char_fd, WFIFOW (char_fd, 2));
+
+ //For data sync
+ if (sd->state.storage_flag == 1)
+ storage_storage_save (sd->status.account_id, 0);
+ else if (sd->state.storage_flag == 2)
+ storage_guild_storagesave (sd->status.account_id, sd->status.guild_id,
+ 0);
+
+ return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_connect (int fd)
+{
+ WFIFOW (fd, 0) = 0x2af8;
+ memcpy (WFIFOP (fd, 2), userid, 24);
+ memcpy (WFIFOP (fd, 26), passwd, 24);
+ WFIFOL (fd, 50) = 0;
+ WFIFOL (fd, 54) = clif_getip ();
+ WFIFOW (fd, 58) = clif_getport (); // [Valaris] thanks to fov
+ WFIFOSET (fd, 60);
+
+ return 0;
+}
+
+/*==========================================
+ * マップ送信
+ *------------------------------------------
+ */
+int chrif_sendmap (int fd)
+{
+ int i;
+
+ WFIFOW (fd, 0) = 0x2afa;
+ for (i = 0; i < map_num; i++)
+ if (map[i].alias[0] != '\0') // [MouseJstr] map aliasing
+ memcpy (WFIFOP (fd, 4 + i * 16), map[i].alias, 16);
+ else
+ memcpy (WFIFOP (fd, 4 + i * 16), map[i].name, 16);
+ WFIFOW (fd, 2) = 4 + i * 16;
+ WFIFOSET (fd, WFIFOW (fd, 2));
+
+ return 0;
+}
+
+/*==========================================
+ * マップ受信
+ *------------------------------------------
+ */
+int chrif_recvmap (int fd)
+{
+ int i, j, ip, port;
+ unsigned char *p = (unsigned char *) &ip;
+
+ if (chrif_state < 2) // まだ準備中
+ return -1;
+
+ ip = RFIFOL (fd, 4);
+ port = RFIFOW (fd, 8);
+ for (i = 10, j = 0; i < RFIFOW (fd, 2); i += 16, j++)
+ {
+ map_setipport (RFIFOP (fd, i), ip, port);
+// if (battle_config.etc_log)
+// printf("recv map %d %s\n", j, RFIFOP(fd,i));
+ }
+ if (battle_config.etc_log)
+ printf ("recv map on %d.%d.%d.%d:%d (%d maps)\n", p[0], p[1], p[2],
+ p[3], port, j);
+
+ return 0;
+}
+
+/*==========================================
+ * マップ鯖間移動のためのデータ準備要求
+ *------------------------------------------
+ */
+int chrif_changemapserver (struct map_session_data *sd, char *name, int x,
+ int y, int ip, short port)
+{
+ int i, s_ip;
+
+ nullpo_retr (-1, sd);
+
+ s_ip = 0;
+ for (i = 0; i < fd_max; i++)
+ if (session[i] && session[i]->session_data == sd)
+ {
+ s_ip = session[i]->client_addr.sin_addr.s_addr;
+ break;
+ }
+
+ WFIFOW (char_fd, 0) = 0x2b05;
+ WFIFOL (char_fd, 2) = sd->bl.id;
+ WFIFOL (char_fd, 6) = sd->login_id1;
+ WFIFOL (char_fd, 10) = sd->login_id2;
+ WFIFOL (char_fd, 14) = sd->status.char_id;
+ memcpy (WFIFOP (char_fd, 18), name, 16);
+ WFIFOW (char_fd, 34) = x;
+ WFIFOW (char_fd, 36) = y;
+ WFIFOL (char_fd, 38) = ip;
+ WFIFOL (char_fd, 42) = port;
+ WFIFOB (char_fd, 44) = sd->status.sex;
+ WFIFOL (char_fd, 45) = s_ip;
+ WFIFOSET (char_fd, 49);
+
+ return 0;
+}
+
+/*==========================================
+ * マップ鯖間移動ack
+ *------------------------------------------
+ */
+int chrif_changemapserverack (int fd)
+{
+ struct map_session_data *sd = map_id2sd (RFIFOL (fd, 2));
+
+ if (sd == NULL || sd->status.char_id != RFIFOL (fd, 14))
+ return -1;
+
+ if (RFIFOL (fd, 6) == 1)
+ {
+ if (battle_config.error_log)
+ printf ("map server change failed.\n");
+ pc_authfail (sd->fd);
+ return 0;
+ }
+ clif_changemapserver (sd, RFIFOP (fd, 18), RFIFOW (fd, 34),
+ RFIFOW (fd, 36), RFIFOL (fd, 38), RFIFOW (fd, 42));
+
+ return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_connectack (int fd)
+{
+ if (RFIFOB (fd, 2))
+ {
+ printf ("Connected to char-server failed %d.\n", RFIFOB (fd, 2));
+ exit (1);
+ }
+ printf ("Connected to char-server (connection #%d).\n", fd);
+ chrif_state = 1;
+
+ chrif_sendmap (fd);
+
+ printf ("chrif: OnCharIfInit event done. (%d events)\n",
+ npc_event_doall ("OnCharIfInit"));
+ printf ("chrif: OnInterIfInit event done. (%d events)\n",
+ npc_event_doall ("OnInterIfInit"));
+
+ // <Agit> Run Event [AgitInit]
+// printf("NPC_Event:[OnAgitInit] do (%d) events (Agit Initialize).\n", npc_event_doall("OnAgitInit"));
+
+ return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_sendmapack (int fd)
+{
+ if (RFIFOB (fd, 2))
+ {
+ printf ("chrif : send map list to char server failed %d\n",
+ RFIFOB (fd, 2));
+ exit (1);
+ }
+
+ memcpy (wisp_server_name, RFIFOP (fd, 3), 24);
+
+ chrif_state = 2;
+
+ return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_authreq (struct map_session_data *sd)
+{
+ int i;
+
+ nullpo_retr (-1, sd);
+
+ if (!sd || !char_fd || !sd->bl.id || !sd->login_id1)
+ return -1;
+
+ for (i = 0; i < fd_max; i++)
+ if (session[i] && session[i]->session_data == sd)
+ {
+ WFIFOW (char_fd, 0) = 0x2afc;
+ WFIFOL (char_fd, 2) = sd->bl.id;
+ WFIFOL (char_fd, 6) = sd->char_id;
+ WFIFOL (char_fd, 10) = sd->login_id1;
+ WFIFOL (char_fd, 14) = sd->login_id2;
+ WFIFOL (char_fd, 18) = session[i]->client_addr.sin_addr.s_addr;
+ WFIFOSET (char_fd, 22);
+ break;
+ }
+
+ return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_charselectreq (struct map_session_data *sd)
+{
+ int i, s_ip;
+
+ nullpo_retr (-1, sd);
+
+ if (!sd || !char_fd || !sd->bl.id || !sd->login_id1)
+ return -1;
+
+ s_ip = 0;
+ for (i = 0; i < fd_max; i++)
+ if (session[i] && session[i]->session_data == sd)
+ {
+ s_ip = session[i]->client_addr.sin_addr.s_addr;
+ break;
+ }
+
+ WFIFOW (char_fd, 0) = 0x2b02;
+ WFIFOL (char_fd, 2) = sd->bl.id;
+ WFIFOL (char_fd, 6) = sd->login_id1;
+ WFIFOL (char_fd, 10) = sd->login_id2;
+ WFIFOL (char_fd, 14) = s_ip;
+ WFIFOSET (char_fd, 18);
+
+ return 0;
+}
+
+/*==========================================
+ * キャラ名問い合わせ
+ *------------------------------------------
+ */
+int chrif_searchcharid (int char_id)
+{
+ if (!char_id)
+ return -1;
+
+ WFIFOW (char_fd, 0) = 0x2b08;
+ WFIFOL (char_fd, 2) = char_id;
+ WFIFOSET (char_fd, 6);
+
+ return 0;
+}
+
+/*==========================================
+ * GMに変化要求
+ *------------------------------------------
+ */
+int chrif_changegm (int id, const char *pass, int len)
+{
+ if (battle_config.etc_log)
+ printf ("chrif_changegm: account: %d, password: '%s'.\n", id, pass);
+
+ WFIFOW (char_fd, 0) = 0x2b0a;
+ WFIFOW (char_fd, 2) = len + 8;
+ WFIFOL (char_fd, 4) = id;
+ memcpy (WFIFOP (char_fd, 8), pass, len);
+ WFIFOSET (char_fd, len + 8);
+
+ return 0;
+}
+
+/*==========================================
+ * Change Email
+ *------------------------------------------
+ */
+int chrif_changeemail (int id, const char *actual_email,
+ const char *new_email)
+{
+ if (battle_config.etc_log)
+ printf
+ ("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n",
+ id, actual_email, new_email);
+
+ WFIFOW (char_fd, 0) = 0x2b0c;
+ WFIFOL (char_fd, 2) = id;
+ memcpy (WFIFOP (char_fd, 6), actual_email, 40);
+ memcpy (WFIFOP (char_fd, 46), new_email, 40);
+ WFIFOSET (char_fd, 86);
+
+ return 0;
+}
+
+/*==========================================
+ * Send message to char-server with a character name to do some operations (by Yor)
+ * Used to ask Char-server about a character name to have the account number to modify account file in login-server.
+ * type of operation:
+ * 1: block
+ * 2: ban
+ * 3: unblock
+ * 4: unban
+ * 5: changesex
+ *------------------------------------------
+ */
+int chrif_char_ask_name (int id, char *character_name, short operation_type,
+ int year, int month, int day, int hour, int minute,
+ int second)
+{
+ WFIFOW (char_fd, 0) = 0x2b0e;
+ WFIFOL (char_fd, 2) = id; // account_id of who ask (for answer) -1 if nobody
+ memcpy (WFIFOP (char_fd, 6), character_name, 24);
+ WFIFOW (char_fd, 30) = operation_type; // type of operation
+ if (operation_type == 2)
+ {
+ WFIFOW (char_fd, 32) = year;
+ WFIFOW (char_fd, 34) = month;
+ WFIFOW (char_fd, 36) = day;
+ WFIFOW (char_fd, 38) = hour;
+ WFIFOW (char_fd, 40) = minute;
+ WFIFOW (char_fd, 42) = second;
+ }
+ printf ("chrif : sended 0x2b0e\n");
+ WFIFOSET (char_fd, 44);
+
+ return 0;
+}
+
+/*==========================================
+ * Answer after a request about a character name to do some operations (by Yor)
+ * Used to answer of chrif_char_ask_name.
+ * type of operation:
+ * 1: block
+ * 2: ban
+ * 3: unblock
+ * 4: unban
+ * 5: changesex
+ * type of answer:
+ * 0: login-server resquest done
+ * 1: player not found
+ * 2: gm level too low
+ * 3: login-server offline
+ *------------------------------------------
+ */
+int chrif_char_ask_name_answer (int fd)
+{
+ int acc;
+ struct map_session_data *sd;
+ char output[256];
+ char player_name[24];
+
+ acc = RFIFOL (fd, 2); // account_id of who has asked (-1 if nobody)
+ memcpy (player_name, RFIFOP (fd, 6), sizeof (player_name));
+ player_name[sizeof (player_name) - 1] = '\0';
+
+ sd = map_id2sd (acc);
+ if (acc >= 0 && sd != NULL)
+ {
+ if (RFIFOW (fd, 32) == 1) // player not found
+ sprintf (output, "The player '%s' doesn't exist.", player_name);
+ else
+ {
+ switch (RFIFOW (fd, 30))
+ {
+ case 1: // block
+ switch (RFIFOW (fd, 32))
+ {
+ case 0: // login-server resquest done
+ sprintf (output,
+ "Login-server has been asked to block the player '%s'.",
+ player_name);
+ break;
+ //case 1: // player not found
+ case 2: // gm level too low
+ sprintf (output,
+ "Your GM level don't authorise you to block the player '%s'.",
+ player_name);
+ break;
+ case 3: // login-server offline
+ sprintf (output,
+ "Login-server is offline. Impossible to block the the player '%s'.",
+ player_name);
+ break;
+ }
+ break;
+ case 2: // ban
+ switch (RFIFOW (fd, 32))
+ {
+ case 0: // login-server resquest done
+ sprintf (output,
+ "Login-server has been asked to ban the player '%s'.",
+ player_name);
+ break;
+ //case 1: // player not found
+ case 2: // gm level too low
+ sprintf (output,
+ "Your GM level don't authorise you to ban the player '%s'.",
+ player_name);
+ break;
+ case 3: // login-server offline
+ sprintf (output,
+ "Login-server is offline. Impossible to ban the the player '%s'.",
+ player_name);
+ break;
+ }
+ break;
+ case 3: // unblock
+ switch (RFIFOW (fd, 32))
+ {
+ case 0: // login-server resquest done
+ sprintf (output,
+ "Login-server has been asked to unblock the player '%s'.",
+ player_name);
+ break;
+ //case 1: // player not found
+ case 2: // gm level too low
+ sprintf (output,
+ "Your GM level don't authorise you to unblock the player '%s'.",
+ player_name);
+ break;
+ case 3: // login-server offline
+ sprintf (output,
+ "Login-server is offline. Impossible to unblock the the player '%s'.",
+ player_name);
+ break;
+ }
+ break;
+ case 4: // unban
+ switch (RFIFOW (fd, 32))
+ {
+ case 0: // login-server resquest done
+ sprintf (output,
+ "Login-server has been asked to unban the player '%s'.",
+ player_name);
+ break;
+ //case 1: // player not found
+ case 2: // gm level too low
+ sprintf (output,
+ "Your GM level don't authorise you to unban the player '%s'.",
+ player_name);
+ break;
+ case 3: // login-server offline
+ sprintf (output,
+ "Login-server is offline. Impossible to unban the the player '%s'.",
+ player_name);
+ break;
+ }
+ break;
+ case 5: // changesex
+ switch (RFIFOW (fd, 32))
+ {
+ case 0: // login-server resquest done
+ sprintf (output,
+ "Login-server has been asked to change the sex of the player '%s'.",
+ player_name);
+ break;
+ //case 1: // player not found
+ case 2: // gm level too low
+ sprintf (output,
+ "Your GM level don't authorise you to change the sex of the player '%s'.",
+ player_name);
+ break;
+ case 3: // login-server offline
+ sprintf (output,
+ "Login-server is offline. Impossible to change the sex of the the player '%s'.",
+ player_name);
+ break;
+ }
+ break;
+ }
+ }
+ if (output[0] != '\0')
+ {
+ output[sizeof (output) - 1] = '\0';
+ clif_displaymessage (sd->fd, output);
+ }
+ }
+ else
+ printf ("chrif_char_ask_name_answer failed - player not online.\n");
+
+ return 0;
+}
+
+/*==========================================
+ * End of GM change (@GM) (modified by Yor)
+ *------------------------------------------
+ */
+int chrif_changedgm (int fd)
+{
+ int acc, level;
+ struct map_session_data *sd = NULL;
+
+ acc = RFIFOL (fd, 2);
+ level = RFIFOL (fd, 6);
+
+ sd = map_id2sd (acc);
+
+ if (battle_config.etc_log)
+ printf ("chrif_changedgm: account: %d, GM level 0 -> %d.\n", acc,
+ level);
+ if (sd != NULL)
+ {
+ if (level > 0)
+ clif_displaymessage (sd->fd, "GM modification success.");
+ else
+ clif_displaymessage (sd->fd, "Failure of GM modification.");
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * 性別変化終了 (modified by Yor)
+ *------------------------------------------
+ */
+int chrif_changedsex (int fd)
+{
+ int acc, sex, i;
+ struct map_session_data *sd;
+ struct pc_base_job s_class;
+
+ acc = RFIFOL (fd, 2);
+ sex = RFIFOL (fd, 6);
+ if (battle_config.etc_log)
+ printf ("chrif_changedsex %d.\n", acc);
+ sd = map_id2sd (acc);
+ if (acc > 0)
+ {
+ if (sd != NULL && sd->status.sex != sex)
+ {
+ s_class = pc_calc_base_job (sd->status.pc_class);
+ if (sd->status.sex == 0)
+ {
+ sd->status.sex = 1;
+ sd->sex = 1;
+ }
+ else if (sd->status.sex == 1)
+ {
+ sd->status.sex = 0;
+ sd->sex = 0;
+ }
+ // to avoid any problem with equipment and invalid sex, equipment is unequiped.
+ for (i = 0; i < MAX_INVENTORY; i++)
+ {
+ if (sd->status.inventory[i].nameid
+ && sd->status.inventory[i].equip)
+ pc_unequipitem ((struct map_session_data *) sd, i, 0);
+ }
+ // reset skill of some job
+ if (s_class.job == 19 || s_class.job == 4020
+ || s_class.job == 4042 || s_class.job == 20
+ || s_class.job == 4021 || s_class.job == 4043)
+ {
+
+ clif_updatestatus (sd, SP_SKILLPOINT);
+ // change job if necessary
+ if (s_class.job == 20 || s_class.job == 4021
+ || s_class.job == 4043)
+ sd->status.pc_class -= 1;
+ else if (s_class.job == 19 || s_class.job == 4020
+ || s_class.job == 4042)
+ sd->status.pc_class += 1;
+ }
+ // save character
+ chrif_save (sd);
+ sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
+ // do same modify in login-server for the account, but no in char-server (it ask again login_id1 to login, and don't remember it)
+ clif_displaymessage (sd->fd,
+ "Your sex has been changed (need disconexion by the server)...");
+ clif_setwaitclose (sd->fd); // forced to disconnect for the change
+ }
+ }
+ else
+ {
+ if (sd != NULL)
+ {
+ printf ("chrif_changedsex failed.\n");
+ }
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * アカウント変数保存要求
+ *------------------------------------------
+ */
+int chrif_saveaccountreg2 (struct map_session_data *sd)
+{
+ int p, j;
+ nullpo_retr (-1, sd);
+
+ p = 8;
+ for (j = 0; j < sd->status.account_reg2_num; j++)
+ {
+ struct global_reg *reg = &sd->status.account_reg2[j];
+ if (reg->str[0] && reg->value != 0)
+ {
+ memcpy (WFIFOP (char_fd, p), reg->str, 32);
+ WFIFOL (char_fd, p + 32) = reg->value;
+ p += 36;
+ }
+ }
+ WFIFOW (char_fd, 0) = 0x2b10;
+ WFIFOW (char_fd, 2) = p;
+ WFIFOL (char_fd, 4) = sd->bl.id;
+ WFIFOSET (char_fd, p);
+
+ return 0;
+}
+
+/*==========================================
+ * アカウント変数通知
+ *------------------------------------------
+ */
+int chrif_accountreg2 (int fd)
+{
+ int j, p;
+ struct map_session_data *sd;
+
+ if ((sd = map_id2sd (RFIFOL (fd, 4))) == NULL)
+ return 1;
+
+ for (p = 8, j = 0; p < RFIFOW (fd, 2) && j < ACCOUNT_REG2_NUM;
+ p += 36, j++)
+ {
+ memcpy (sd->status.account_reg2[j].str, RFIFOP (fd, p), 32);
+ sd->status.account_reg2[j].value = RFIFOL (fd, p + 32);
+ }
+ sd->status.account_reg2_num = j;
+// printf("chrif: accountreg2\n");
+
+ return 0;
+}
+
+/*==========================================
+ * Divorce request from char server
+ * triggered on account deletion or as an
+ * ack from a map-server divorce request
+ *------------------------------------------
+ */
+int chrif_divorce (int char_id, int partner_id)
+{
+ struct map_session_data *sd = NULL;
+
+ if (!char_id || !partner_id)
+ return 0;
+
+ sd = map_nick2sd (map_charid2nick (char_id));
+ if (sd && sd->status.partner_id == partner_id)
+ {
+ sd->status.partner_id = 0;
+
+ if (sd->npc_flags.divorce)
+ {
+ sd->npc_flags.divorce = 0;
+ map_scriptcont (sd, sd->npc_id);
+ }
+ }
+
+ nullpo_retr (0, sd = map_nick2sd (map_charid2nick (partner_id)));
+ if (sd->status.partner_id == char_id)
+ sd->status.partner_id = 0;
+
+ return 0;
+}
+
+/*==========================================
+ * Tell character server someone is divorced
+ * Needed to divorce when partner is not connected to map server
+ *-------------------------------------
+ */
+int chrif_send_divorce (int char_id)
+{
+ if (char_fd < 0)
+ return -1;
+
+ WFIFOW (char_fd, 0) = 0x2b16;
+ WFIFOL (char_fd, 2) = char_id;
+ WFIFOSET (char_fd, 6);
+ return 0;
+}
+
+/*==========================================
+ * Disconnection of a player (account has been deleted in login-server) by [Yor]
+ *------------------------------------------
+ */
+int chrif_accountdeletion (int fd)
+{
+ int acc;
+ struct map_session_data *sd;
+
+ acc = RFIFOL (fd, 2);
+ if (battle_config.etc_log)
+ printf ("chrif_accountdeletion %d.\n", acc);
+ sd = map_id2sd (acc);
+ if (acc > 0)
+ {
+ if (sd != NULL)
+ {
+ sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
+ clif_displaymessage (sd->fd,
+ "Your account has been deleted (disconnection)...");
+ clif_setwaitclose (sd->fd); // forced to disconnect for the change
+ }
+ }
+ else
+ {
+ if (sd != NULL)
+ printf ("chrif_accountdeletion failed - player not online.\n");
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
+ *------------------------------------------
+ */
+int chrif_accountban (int fd)
+{
+ int acc;
+ struct map_session_data *sd;
+
+ acc = RFIFOL (fd, 2);
+ if (battle_config.etc_log)
+ printf ("chrif_accountban %d.\n", acc);
+ sd = map_id2sd (acc);
+ if (acc > 0)
+ {
+ if (sd != NULL)
+ {
+ sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
+ if (RFIFOB (fd, 6) == 0)
+ { // 0: change of statut, 1: ban
+ switch (RFIFOL (fd, 7))
+ { // status or final date of a banishment
+ case 1: // 0 = Unregistered ID
+ clif_displaymessage (sd->fd,
+ "Your account has 'Unregistered'.");
+ break;
+ case 2: // 1 = Incorrect Password
+ clif_displaymessage (sd->fd,
+ "Your account has an 'Incorrect Password'...");
+ break;
+ case 3: // 2 = This ID is expired
+ clif_displaymessage (sd->fd,
+ "Your account has expired.");
+ break;
+ case 4: // 3 = Rejected from Server
+ clif_displaymessage (sd->fd,
+ "Your account has been rejected from server.");
+ break;
+ case 5: // 4 = You have been blocked by the GM Team
+ clif_displaymessage (sd->fd,
+ "Your account has been blocked by the GM Team.");
+ break;
+ case 6: // 5 = Your Game's EXE file is not the latest version
+ clif_displaymessage (sd->fd,
+ "Your Game's EXE file is not the latest version.");
+ break;
+ case 7: // 6 = Your are Prohibited to log in until %s
+ clif_displaymessage (sd->fd,
+ "Your account has been prohibited to log in.");
+ break;
+ case 8: // 7 = Server is jammed due to over populated
+ clif_displaymessage (sd->fd,
+ "Server is jammed due to over populated.");
+ break;
+ case 9: // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
+ clif_displaymessage (sd->fd,
+ "Your account has not more authorised.");
+ break;
+ case 100: // 99 = This ID has been totally erased
+ clif_displaymessage (sd->fd,
+ "Your account has been totally erased.");
+ break;
+ default:
+ clif_displaymessage (sd->fd,
+ "Your account has not more authorised.");
+ break;
+ }
+ }
+ else if (RFIFOB (fd, 6) == 1)
+ { // 0: change of statut, 1: ban
+ time_t timestamp;
+ char tmpstr[2048];
+ timestamp = (time_t) RFIFOL (fd, 7); // status or final date of a banishment
+ strcpy (tmpstr, "Your account has been banished until ");
+ strftime (tmpstr + strlen (tmpstr), 24, "%d-%m-%Y %H:%M:%S",
+ gmtime (&timestamp));
+ clif_displaymessage (sd->fd, tmpstr);
+ }
+ clif_setwaitclose (sd->fd); // forced to disconnect for the change
+ }
+ }
+ else
+ {
+ if (sd != NULL)
+ printf ("chrif_accountban failed - player not online.\n");
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * Receiving GM accounts and their levels from char-server by [Yor]
+ *------------------------------------------
+ */
+int chrif_recvgmaccounts (int fd)
+{
+ printf ("From login-server: receiving of %d GM accounts information.\n",
+ pc_read_gm_account (fd));
+
+ return 0;
+}
+
+/*==========================================
+ * Request to reload GM accounts and their levels: send to char-server by [Yor]
+ *------------------------------------------
+ */
+int chrif_reloadGMdb (void)
+{
+
+ WFIFOW (char_fd, 0) = 0x2af7;
+ WFIFOSET (char_fd, 2);
+
+ return 0;
+}
+
+/*==========================================
+ * Send rates and motd to char server [Wizputer]
+ *------------------------------------------
+ */
+int chrif_ragsrvinfo (int base_rate, int job_rate, int drop_rate)
+{
+ char buf[256];
+ FILE *fp;
+ int i;
+
+ WFIFOW (char_fd, 0) = 0x2b16;
+ WFIFOW (char_fd, 2) = base_rate;
+ WFIFOW (char_fd, 4) = job_rate;
+ WFIFOW (char_fd, 6) = drop_rate;
+
+ if ((fp = fopen_ (motd_txt, "r")) != NULL)
+ {
+ if (fgets (buf, 250, fp) != NULL)
+ {
+ for (i = 0; buf[i]; i++)
+ {
+ if (buf[i] == '\r' || buf[i] == '\n')
+ {
+ buf[i] = 0;
+ break;
+ }
+ }
+ WFIFOW (char_fd, 8) = sizeof (buf) + 10;
+ memcpy (WFIFOP (char_fd, 10), buf, sizeof (buf));
+ }
+ fclose_ (fp);
+ }
+ else
+ {
+ WFIFOW (char_fd, 8) = sizeof (buf) + 10;
+ memcpy (WFIFOP (char_fd, 10), buf, sizeof (buf));
+ }
+ WFIFOSET (char_fd, WFIFOW (char_fd, 8));
+
+ return 0;
+}
+
+/*=========================================
+ * Tell char-server charcter disconnected [Wizputer]
+ *-----------------------------------------
+ */
+
+int chrif_char_offline (struct map_session_data *sd)
+{
+ if (char_fd < 0)
+ return -1;
+
+ WFIFOW (char_fd, 0) = 0x2b17;
+ WFIFOL (char_fd, 2) = sd->status.char_id;
+ WFIFOSET (char_fd, 6);
+
+ return 0;
+}
+
+/*========================================
+ * Map item IDs
+ *----------------------------------------
+ */
+
+static void ladmin_itemfrob_fix_item (int source, int dest, struct item *item)
+{
+ if (item && item->nameid == source)
+ {
+ item->nameid = dest;
+ item->equip = 0;
+ }
+}
+
+static int ladmin_itemfrob_c2 (struct block_list *bl, int source_id,
+ int dest_id)
+{
+#define IFIX(v) if (v == source_id) {v = dest_id; }
+#define FIX(item) ladmin_itemfrob_fix_item(source_id, dest_id, &item)
+
+ if (!bl)
+ return 0;
+
+ switch (bl->type)
+ {
+ case BL_PC:
+ {
+ struct map_session_data *pc = (struct map_session_data *) bl;
+ struct storage *stor = account2storage2 (pc->status.account_id);
+ int j;
+
+ for (j = 0; j < MAX_INVENTORY; j++)
+ IFIX (pc->status.inventory[j].nameid);
+ for (j = 0; j < MAX_CART; j++)
+ IFIX (pc->status.cart[j].nameid);
+ IFIX (pc->status.weapon);
+ IFIX (pc->status.shield);
+ IFIX (pc->status.head_top);
+ IFIX (pc->status.head_mid);
+ IFIX (pc->status.head_bottom);
+
+ if (stor)
+ for (j = 0; j < stor->storage_amount; j++)
+ FIX (stor->storage_[j]);
+
+ for (j = 0; j < MAX_INVENTORY; j++)
+ {
+ struct item_data *item = pc->inventory_data[j];
+ if (item && item->nameid == source_id)
+ {
+ item->nameid = dest_id;
+ if (item->equip)
+ pc_unequipitem (pc, j, 0);
+ item->nameid = dest_id;
+ }
+ }
+
+ break;
+ }
+
+ case BL_MOB:
+ {
+ struct mob_data *mob = (struct mob_data *) bl;
+ int i;
+ for (i = 0; i < mob->lootitem_count; i++)
+ FIX (mob->lootitem[i]);
+ break;
+ }
+
+ case BL_ITEM:
+ {
+ struct flooritem_data *item = (struct flooritem_data *) bl;
+ FIX (item->item_data);
+ break;
+ }
+ }
+#undef FIX
+#undef IFIX
+
+ return 0;
+}
+
+int ladmin_itemfrob_c (struct block_list *bl, va_list va_args)
+{
+ int source_id = va_arg (va_args, int);
+ int dest_id = va_arg (va_args, int);
+ return ladmin_itemfrob_c2 (bl, source_id, dest_id);
+}
+
+void ladmin_itemfrob (int fd)
+{
+ int source_id = RFIFOL (fd, 2);
+ int dest_id = RFIFOL (fd, 6);
+ struct block_list *bl = (struct block_list *) map_get_first_session ();
+
+ // flooritems
+ map_foreachobject (ladmin_itemfrob_c, 0 /* any object */ , source_id,
+ dest_id);
+
+ // player characters (and, hopefully, mobs)
+ while (bl->next)
+ {
+ ladmin_itemfrob_c2 (bl, source_id, dest_id);
+ bl = bl->next;
+ }
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_parse (int fd)
+{
+ int packet_len, cmd;
+
+ // only char-server can have an access to here.
+ // so, if it isn't the char-server, we disconnect the session (fd != char_fd).
+ if (fd != char_fd || session[fd]->eof)
+ {
+ if (fd == char_fd)
+ {
+ printf
+ ("Map-server can't connect to char-server (connection #%d).\n",
+ fd);
+ char_fd = -1;
+ }
+ close (fd);
+ delete_session (fd);
+ return;
+ }
+
+ while (RFIFOREST (fd) >= 2)
+ {
+ cmd = RFIFOW (fd, 0);
+ if (cmd < 0x2af8
+ || cmd >=
+ 0x2af8 +
+ (sizeof (packet_len_table) / sizeof (packet_len_table[0]))
+ || packet_len_table[cmd - 0x2af8] == 0)
+ {
+
+ int r = intif_parse (fd); // intifに渡す
+
+ if (r == 1)
+ continue; // intifで処理した
+ if (r == 2)
+ return; // intifで処理したが、データが足りない
+
+ session[fd]->eof = 1;
+ return;
+ }
+ packet_len = packet_len_table[cmd - 0x2af8];
+ if (packet_len == -1)
+ {
+ if (RFIFOREST (fd) < 4)
+ return;
+ packet_len = RFIFOW (fd, 2);
+ }
+ if (RFIFOREST (fd) < packet_len)
+ return;
+
+ switch (cmd)
+ {
+ case 0x2af9:
+ chrif_connectack (fd);
+ break;
+ case 0x2afa:
+ ladmin_itemfrob (fd);
+ break;
+ case 0x2afb:
+ chrif_sendmapack (fd);
+ break;
+ case 0x2afd:
+ pc_authok (RFIFOL (fd, 4), RFIFOL (fd, 8),
+ (time_t) RFIFOL (fd, 12), RFIFOW (fd, 16),
+ (struct mmo_charstatus *) RFIFOP (fd, 18));
+ break;
+ case 0x2afe:
+ pc_authfail (RFIFOL (fd, 2));
+ break;
+ case 0x2b00:
+ map_setusers (RFIFOL (fd, 2));
+ break;
+ case 0x2b03:
+ clif_charselectok (RFIFOL (fd, 2));
+ break;
+ case 0x2b04:
+ chrif_recvmap (fd);
+ break;
+ case 0x2b06:
+ chrif_changemapserverack (fd);
+ break;
+ case 0x2b09:
+ map_addchariddb (RFIFOL (fd, 2), RFIFOP (fd, 6));
+ break;
+ case 0x2b0b:
+ chrif_changedgm (fd);
+ break;
+ case 0x2b0d:
+ chrif_changedsex (fd);
+ break;
+ case 0x2b0f:
+ chrif_char_ask_name_answer (fd);
+ break;
+ case 0x2b11:
+ chrif_accountreg2 (fd);
+ break;
+ case 0x2b12:
+ chrif_divorce (RFIFOL (fd, 2), RFIFOL (fd, 6));
+ break;
+ case 0x2b13:
+ chrif_accountdeletion (fd);
+ break;
+ case 0x2b14:
+ chrif_accountban (fd);
+ break;
+ case 0x2b15:
+ chrif_recvgmaccounts (fd);
+ break;
+
+ default:
+ if (battle_config.error_log)
+ printf ("chrif_parse : unknown packet %d %d\n", fd,
+ RFIFOW (fd, 0));
+ session[fd]->eof = 1;
+ return;
+ }
+ RFIFOSKIP (fd, packet_len);
+ }
+}
+
+/*==========================================
+ * timer関数
+ * 今このmap鯖に繋がっているクライアント人数をchar鯖へ送る
+ *------------------------------------------
+ */
+void send_users_tochar (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+ int users = 0, i;
+ struct map_session_data *sd;
+
+ if (char_fd <= 0 || session[char_fd] == NULL)
+ return;
+
+ WFIFOW (char_fd, 0) = 0x2aff;
+ for (i = 0; i < fd_max; i++)
+ {
+ if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth &&
+ !((battle_config.hide_GM_session
+ || sd->state.shroud_active
+ || (sd->status.option & OPTION_HIDE)) && pc_isGM (sd)))
+ {
+ WFIFOL (char_fd, 6 + 4 * users) = sd->status.char_id;
+ users++;
+ }
+ }
+ WFIFOW (char_fd, 2) = 6 + 4 * users;
+ WFIFOW (char_fd, 4) = users;
+ WFIFOSET (char_fd, 6 + 4 * users);
+}
+
+/*==========================================
+ * timer関数
+ * char鯖との接続を確認し、もし切れていたら再度接続する
+ *------------------------------------------
+ */
+void check_connect_char_server (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+ if (char_fd <= 0 || session[char_fd] == NULL)
+ {
+ printf ("Attempt to connect to char-server...\n");
+ chrif_state = 0;
+ if ((char_fd = make_connection (char_ip, char_port)) < 0)
+ return;
+ session[char_fd]->func_parse = chrif_parse;
+ realloc_fifo (char_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
+
+ chrif_connect (char_fd);
+ }
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int do_init_chrif (void)
+{
+// add_timer_func_list (check_connect_char_server, "check_connect_char_server");
+// add_timer_func_list (send_users_tochar, "send_users_tochar");
+ add_timer_interval (gettick () + 1000, check_connect_char_server, 0, 0,
+ 10 * 1000);
+ add_timer_interval (gettick () + 1000, send_users_tochar, 0, 0, 5 * 1000);
+
+ return 0;
+}