summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-03-04 22:22:30 -0300
committershennetsind <ind@henn.et>2013-03-04 22:22:30 -0300
commit0241d0195558b7e57d2181f2f097cf774a1ef463 (patch)
treeb39dda78be8a10722ff10f507c0e5945052f91a3
parent03c5ecd61753391b7790cf72f9cc629e9f8bbc38 (diff)
downloadhercules-0241d0195558b7e57d2181f2f097cf774a1ef463.tar.gz
hercules-0241d0195558b7e57d2181f2f097cf774a1ef463.tar.bz2
hercules-0241d0195558b7e57d2181f2f097cf774a1ef463.tar.xz
hercules-0241d0195558b7e57d2181f2f097cf774a1ef463.zip
Introducing account-dependent character slot count
As requested in http://hercules.ws/board/topic/248-reserved-slot-system/ Signed-off-by: shennetsind <ind@henn.et>
-rw-r--r--sql-files/main.sql1
-rw-r--r--sql-files/upgrades/2013-03-05--01-05.sql3
-rw-r--r--sql-files/upgrades/index.txt3
-rw-r--r--src/char/char.c44
-rw-r--r--src/login/account.h1
-rw-r--r--src/login/account_sql.c9
-rw-r--r--src/login/login.c17
7 files changed, 51 insertions, 27 deletions
diff --git a/sql-files/main.sql b/sql-files/main.sql
index c6b5c74d8..2064e6863 100644
--- a/sql-files/main.sql
+++ b/sql-files/main.sql
@@ -646,6 +646,7 @@ CREATE TABLE IF NOT EXISTS `sql_updates` (
-- Existent updates to enter
INSERT INTO `sql_updates` (`timestamp`) VALUES (1360858500);
INSERT INTO `sql_updates` (`timestamp`) VALUES (1360951560);
+INSERT INTO `sql_updates` (`timestamp`) VALUES (1362445531);
--
-- Table structure for table `sstatus`
diff --git a/sql-files/upgrades/2013-03-05--01-05.sql b/sql-files/upgrades/2013-03-05--01-05.sql
new file mode 100644
index 000000000..4a1e23807
--- /dev/null
+++ b/sql-files/upgrades/2013-03-05--01-05.sql
@@ -0,0 +1,3 @@
+#1362445531
+ALTER TABLE `login` ADD `character_slots` TINYINT( 3 ) UNSIGNED NOT NULL;
+INSERT INTO `sql_updates` (`timestamp`) VALUES (1362445531); \ No newline at end of file
diff --git a/sql-files/upgrades/index.txt b/sql-files/upgrades/index.txt
index 3d4df8c23..bd835414c 100644
--- a/sql-files/upgrades/index.txt
+++ b/sql-files/upgrades/index.txt
@@ -1,2 +1,3 @@
2013-02-14--16-15.sql
-2013-02-15--18-06.sql \ No newline at end of file
+2013-02-15--18-06.sql
+2013-03-05--01-05.sql \ No newline at end of file
diff --git a/src/char/char.c b/src/char/char.c
index cd1b1da66..aed678684 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -128,6 +128,7 @@ struct char_session_data {
char email[40]; // e-mail (default: a@a.com) by [Yor]
time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
int group_id; // permission
+ uint8 char_slots;
uint32 version;
uint8 clienttype;
char new_name[NAME_LENGTH];
@@ -1488,17 +1489,21 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag
flag = check_char_name(name,esc_name);
if( flag < 0 )
return flag;
-
+
//check other inputs
#if PACKETVER >= 20120307
- if(slot >= MAX_CHARS)
+ if(slot >= sd->char_slots)
#else
- if((slot >= MAX_CHARS) // slots
+ if((slot >= sd->char_slots) // slots
|| (str + agi + vit + int_ + dex + luk != 6*5 ) // stats
|| (str < 1 || str > 9 || agi < 1 || agi > 9 || vit < 1 || vit > 9 || int_ < 1 || int_ > 9 || dex < 1 || dex > 9 || luk < 1 || luk > 9) // individual stat values
|| (str + int_ != 10 || agi + luk != 10 || vit + dex != 10) ) // pairs
#endif
+#if PACKETVER >= 20100413
+ return -4; // invalid slot
+#else
return -2; // invalid input
+#endif
// check the number of already existing chars in this account
@@ -1863,8 +1868,8 @@ int mmo_char_send006b(int fd, struct char_session_data* sd)
WFIFOW(fd,0) = 0x6b;
#if PACKETVER >= 20100413
WFIFOB(fd,4) = MAX_CHARS; // Max slots.
- WFIFOB(fd,5) = MAX_CHARS; // Available slots.
- WFIFOB(fd,6) = MAX_CHARS; // Premium slots.
+ WFIFOB(fd,5) = sd->char_slots; // Available slots. (aka PremiumStartSlot)
+ WFIFOB(fd,6) = MAX_CHARS; // Premium slots. AKA any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red
#endif
memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes
j+=mmo_chars_fromsql(sd, WFIFOP(fd,j));
@@ -2144,7 +2149,7 @@ int parse_fromlogin(int fd) {
break;
case 0x2717: // account data
- if (RFIFOREST(fd) < 62)
+ if (RFIFOREST(fd) < 63)
return 0;
// find the authenticated session with this account id
@@ -2155,7 +2160,13 @@ int parse_fromlogin(int fd) {
memcpy(sd->email, RFIFOP(fd,6), 40);
sd->expiration_time = (time_t)RFIFOL(fd,46);
sd->group_id = RFIFOB(fd,50);
- safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,51), sizeof(sd->birthdate));
+ sd->char_slots = RFIFOB(fd,51);
+ if( sd->char_slots > MAX_CHARS ) {
+ ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.h! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots);
+ sd->char_slots = MAX_CHARS;/* cap to maximum */
+ } else if ( !sd->char_slots )/* no value aka 0 in sql */
+ sd->char_slots = MAX_CHARS;/* cap to maximum */
+ safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate));
ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] );
// continued from char_auth_ok...
if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359
@@ -2181,7 +2192,7 @@ int parse_fromlogin(int fd) {
#endif
}
}
- RFIFOSKIP(fd,62);
+ RFIFOSKIP(fd,63);
break;
// login-server alive packet
@@ -3903,19 +3914,20 @@ int parse_char(int fd)
#endif
//'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3)
- if (i < 0)
- {
+ if (i < 0) {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x6e;
+ /* Others I found [Ind] */
+ /* 0x02 = Symbols in Character Names are forbidden */
+ /* 0x03 = You are not elegible to open the Character Slot. */
switch (i) {
- case -1: WFIFOB(fd,2) = 0x00; break;
- case -2: WFIFOB(fd,2) = 0xFF; break;
- case -3: WFIFOB(fd,2) = 0x01; break;
+ case -1: WFIFOB(fd,2) = 0x00; break;
+ case -2: WFIFOB(fd,2) = 0xFF; break;
+ case -3: WFIFOB(fd,2) = 0x01; break;
+ case -4: WFIFOB(fd,2) = 0x03; break;
}
WFIFOSET(fd,3);
- }
- else
- {
+ } else {
int len;
// retrieve data
struct mmo_charstatus char_dat;
diff --git a/src/login/account.h b/src/login/account.h
index adbcb7102..56708d5e9 100644
--- a/src/login/account.h
+++ b/src/login/account.h
@@ -42,6 +42,7 @@ struct mmo_account
char sex; // gender (M/F/S)
char email[40]; // e-mail (by default: a@a.com)
int group_id; // player group id
+ uint8 char_slots; // this accounts maximum character slots (maximum is limited to MAX_CHARS define in char server)
unsigned int state; // packet 0x006a value + 1 (0: compte OK)
time_t unban_time; // (timestamp): ban time limit of the account (0 = no ban)
time_t expiration_time; // (timestamp): validity limit of the account (0 = unlimited)
diff --git a/src/login/account_sql.c b/src/login/account_sql.c
index f89147334..f8c39efc9 100644
--- a/src/login/account_sql.c
+++ b/src/login/account_sql.c
@@ -522,7 +522,7 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc
// retrieve login entry for the specified account
if( SQL_ERROR == Sql_Query(sql_handle,
- "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate` FROM `%s` WHERE `account_id` = %d",
+ "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate`,`character_slots` FROM `%s` WHERE `account_id` = %d",
db->account_db, account_id )
) {
Sql_ShowDebug(sql_handle);
@@ -548,6 +548,7 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc
Sql_GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin));
Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip));
Sql_GetData(sql_handle, 12, &data, NULL); safestrncpy(acc->birthdate, data, sizeof(acc->birthdate));
+ Sql_GetData(sql_handle, 13, &data, NULL); acc->char_slots = atoi(data);
Sql_FreeResult(sql_handle);
@@ -596,7 +597,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
if( is_new )
{// insert into account table
if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
- "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`, `character_slots`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
db->account_db)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, (void*)&acc->account_id, sizeof(acc->account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid))
@@ -611,6 +612,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate))
+ || SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_UCHAR, (void*)&acc->char_slots, sizeof(acc->char_slots))
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
@@ -619,7 +621,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
}
else
{// update account table
- if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id)
+ if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=?,`character_slots`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex))
@@ -632,6 +634,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 9, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate))
+ || SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_UCHAR, (void*)&acc->char_slots, sizeof(acc->char_slots))
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
diff --git a/src/login/login.c b/src/login/login.c
index 54f066b53..e174672cc 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -557,6 +557,7 @@ int parse_fromchar(int fd)
time_t expiration_time = 0;
char email[40] = "";
int group_id = 0;
+ uint8 char_slots = 0;
char birthdate[10+1] = "";
int account_id = RFIFOL(fd,2);
@@ -564,22 +565,23 @@ int parse_fromchar(int fd)
if( !accounts->load_num(accounts, &acc, account_id) )
ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", server[id].name, account_id, ip);
- else
- {
+ else {
safestrncpy(email, acc.email, sizeof(email));
expiration_time = acc.expiration_time;
group_id = acc.group_id;
+ char_slots = acc.char_slots;
safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
}
- WFIFOHEAD(fd,62);
+ WFIFOHEAD(fd,63);
WFIFOW(fd,0) = 0x2717;
WFIFOL(fd,2) = account_id;
safestrncpy((char*)WFIFOP(fd,6), email, 40);
WFIFOL(fd,46) = (uint32)expiration_time;
- WFIFOB(fd,50) = group_id;
- safestrncpy((char*)WFIFOP(fd,51), birthdate, 10+1);
- WFIFOSET(fd,62);
+ WFIFOB(fd,50) = (unsigned char)group_id;
+ WFIFOB(fd,51) = char_slots;
+ safestrncpy((char*)WFIFOP(fd,52), birthdate, 10+1);
+ WFIFOSET(fd,63);
}
break;
@@ -956,7 +958,8 @@ int mmo_auth_new(const char* userid, const char* pass, const char sex, const cha
safestrncpy(acc.lastlogin, "0000-00-00 00:00:00", sizeof(acc.lastlogin));
safestrncpy(acc.last_ip, last_ip, sizeof(acc.last_ip));
safestrncpy(acc.birthdate, "0000-00-00", sizeof(acc.birthdate));
-
+ acc.char_slots = 0;
+
if( !accounts->create(accounts, &acc) )
return 0;