Adding charblock

Update HC 0x20d to send the blocklist value, based on Herc:aee2f631
Revamp ZH 0x2b0e and HA 0x2725 to send difftime instead
year,month,day,minutes,secondes values..
Remove duplicate code for char_ban
Add missing sql_upgrade for vip
This commit is contained in:
lighta 2013-11-18 20:38:10 -05:00
parent 30648216ec
commit 3428ae297a
13 changed files with 310 additions and 282 deletions

View File

@ -103,10 +103,10 @@
82: Please provide a name or number from the list provided: 82: Please provide a name or number from the list provided:
83: Monster 'Emperium' cannot be spawned. 83: Monster 'Emperium' cannot be spawned.
84: All stats changed! 84: All stats changed!
85: Invalid time for ban command. 85: Invalid time for %s command (time=%d).
86: Sorry, player names have to be at least 4 characters. 86: Sorry, player names have to be at least 4 characters.
87: Sorry, player names can be no longer than 23 characters. 87: Sorry, player names can be no longer than 23 characters.
88: Sending request to login server... 88: Sending request to %s server...
89: Night mode is already enabled. 89: Night mode is already enabled.
90: Day mode is already enabled. 90: Day mode is already enabled.
91: Character's base level can't go any higher. 91: Character's base level can't go any higher.
@ -439,8 +439,8 @@
419: Server is jammed due to over populated. 419: Server is jammed due to over populated.
420: Your account has not more authorised. 420: Your account has not more authorised.
421: Your account has been totally erased. 421: Your account has been totally erased.
423: Your account has been banished until 423: Your %s has been banished until %s
424: Login-server has been asked to %s the player '%.*s'. 424: %s has been asked to %s the player '%.*s'.
425: The player '%.*s' doesn't exist. 425: The player '%.*s' doesn't exist.
426: Your GM level don't authorise you to %s the player '%.*s'. 426: Your GM level don't authorise you to %s the player '%.*s'.
427: Login-server is offline. Impossible to %s the player '%.*s'. 427: Login-server is offline. Impossible to %s the player '%.*s'.
@ -450,6 +450,10 @@
431: unban 431: unban
432: change the sex of 432: change the sex of
433: This character has been banned until
434: Char-server has been asked to %s the character '%.*s'.
435: Please enter a player name (usage: @charunblock <char name>).
// Homunculus messages // Homunculus messages
450: You already have a homunculus 450: You already have a homunculus
@ -851,7 +855,7 @@
// @charban // @charban
1022: Please enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <char name>). 1022: Please enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <char name>).
1023: You are not allowed to reduce the length of a ban. 1023: You are not allowed to alter the time of a ban.
// @charunblock // @charunblock
1024: Please enter a player name (usage: @charunblock <char name>). 1024: Please enter a player name (usage: @charunblock <char name>).

View File

@ -122,6 +122,7 @@ CREATE TABLE IF NOT EXISTS `char` (
`rename` SMALLINT(3) unsigned NOT NULL default '0', `rename` SMALLINT(3) unsigned NOT NULL default '0',
`delete_date` INT(11) UNSIGNED NOT NULL DEFAULT '0', `delete_date` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`moves` int(11) unsigned NOT NULL DEFAULT '0', `moves` int(11) unsigned NOT NULL DEFAULT '0',
`unban_time` int(11) unsigned NOT NULL default '0',
PRIMARY KEY (`char_id`), PRIMARY KEY (`char_id`),
UNIQUE KEY `name_key` (`name`), UNIQUE KEY `name_key` (`name`),
KEY `account_id` (`account_id`), KEY `account_id` (`account_id`),

View File

@ -1,4 +1,4 @@
ALTER TABLE `inventory` MODIFY `equip` int(11) unsigned NOT NULL default '0'; ALTER TABLE `inventory` MODIFY `equip` int(11) unsigned NOT NULL default '0';
ALTER TABLE `storage` MODIFY `equip` int(11) unsigned NOT NULL default '0'; ALTER TABLE `storage` MODIFY `equip` int(11) unsigned NOT NULL default '0';
ALTER TABLE `cart_inventory` MODIFY `equip` int(11) unsigned NOT NULL default '0'; ALTER TABLE `cart_inventory` MODIFY `equip` int(11) unsigned NOT NULL default '0';
ALTER TABLE `guild_storage` MODIFY `equip` int(11) unsigned NOT NULL default '0'; ALTER TABLE `guild_storage` MODIFY `equip` int(11) unsigned NOT NULL default '0';

View File

@ -0,0 +1,3 @@
ALTER TABLE `login` ADD `vip_time` int(11) UNSIGNED NULL DEFAULT '0';
ALTER TABLE `login` ADD `old_group` tinyint(3) NOT NULL default '0';
ALTER TABLE `char` ADD `unban_time` int(11) unsigned NOT NULL default '0';

View File

@ -148,6 +148,7 @@ struct char_session_data {
int bank_vault; int bank_vault;
unsigned int char_moves[MAX_CHARS]; // character moves left unsigned int char_moves[MAX_CHARS]; // character moves left
uint8 isvip; uint8 isvip;
time_t unban_time[MAX_CHARS];
}; };
struct startitem { struct startitem {
@ -543,7 +544,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->pet_id != cp->pet_id) || (p->weapon != cp->weapon) || (p->hom_id != cp->hom_id) || (p->pet_id != cp->pet_id) || (p->weapon != cp->weapon) || (p->hom_id != cp->hom_id) ||
(p->ele_id != cp->ele_id) || (p->shield != cp->shield) || (p->head_top != cp->head_top) || (p->ele_id != cp->ele_id) || (p->shield != cp->shield) || (p->head_top != cp->head_top) ||
(p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) || (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) ||
(p->rename != cp->rename) || (p->robe != cp->robe) || (p->character_moves != cp->character_moves) (p->rename != cp->rename) || (p->robe != cp->robe) || (p->character_moves != cp->character_moves) || (p->unban_time != cp->unban_time)
) )
{ //Save status { //Save status
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d'," if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d',"
@ -553,7 +554,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
"`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d'," "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d',"
"`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d',"
"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
"`delete_date`='%lu',`robe`='%d',`moves`='%d'" "`delete_date`='%lu',`robe`='%d',`moves`='%d', `unban_time`='%d'"
" WHERE `account_id`='%d' AND `char_id` = '%d'", " WHERE `account_id`='%d' AND `char_id` = '%d'",
char_db, p->base_level, p->job_level, char_db, p->base_level, p->job_level,
p->base_exp, p->job_exp, p->zeny, p->base_exp, p->job_exp, p->zeny,
@ -564,7 +565,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y, mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y,
mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename, mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename,
(unsigned long)p->delete_date, // FIXME: platform-dependent size (unsigned long)p->delete_date, // FIXME: platform-dependent size
p->robe,p->character_moves, p->robe,p->character_moves,p->unban_time,
p->account_id, p->char_id) ) p->account_id, p->char_id) )
{ {
Sql_ShowDebug(sql_handle); Sql_ShowDebug(sql_handle);
@ -1095,7 +1096,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
"`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`," "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`," "`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`,"
"`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`," "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`,"
"`robe`,`moves`" "`robe`,`moves`, `unban_time`"
" FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS) " FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS)
|| SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_Execute(stmt)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &p.char_id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &p.char_id, 0, NULL, NULL)
@ -1135,6 +1136,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_UINT, &p.character_moves, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_UINT, &p.character_moves, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 37, SQLDT_LONG, &p.unban_time, 0, NULL, NULL)
) )
{ {
SqlStmt_ShowDebug(stmt); SqlStmt_ShowDebug(stmt);
@ -1146,6 +1148,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
{ {
p.last_point.map = mapindex_name2id(last_map); p.last_point.map = mapindex_name2id(last_map);
sd->found_char[p.slot] = p.char_id; sd->found_char[p.slot] = p.char_id;
sd->unban_time[p.slot] = p.unban_time;
j += mmo_char_tobuf(WBUFP(buf, j), &p); j += mmo_char_tobuf(WBUFP(buf, j), &p);
// Addon System // Addon System
@ -1196,7 +1199,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
"`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`," "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`," "`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,"
"`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," "`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`,"
"`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`" "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`, `unban_time`"
" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db) " FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_Execute(stmt)
@ -1229,7 +1232,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 26, SQLDT_INT, &p->guild_id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 26, SQLDT_INT, &p->guild_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 27, SQLDT_INT, &p->pet_id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 27, SQLDT_INT, &p->pet_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 28, SQLDT_INT, &p->hom_id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 28, SQLDT_INT, &p->hom_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_INT, &p->ele_id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_INT, &p->ele_id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p->hair, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p->hair, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p->hair_color, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p->hair_color, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_SHORT, &p->clothes_color, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_SHORT, &p->clothes_color, 0, NULL, NULL)
@ -1249,10 +1252,11 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_INT, &p->mother, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_INT, &p->mother, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_INT, &p->child, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_INT, &p->child, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_INT, &p->fame, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_INT, &p->fame, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_SHORT, &p->rename, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_SHORT, &p->rename, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 51, SQLDT_SHORT, &p->robe, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 51, SQLDT_SHORT, &p->robe, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 52, SQLDT_UINT32, &p->character_moves, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 52, SQLDT_UINT32, &p->character_moves, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 53, SQLDT_LONG, &p->unban_time, 0, NULL, NULL)
) )
{ {
SqlStmt_ShowDebug(stmt); SqlStmt_ShowDebug(stmt);
@ -1958,11 +1962,32 @@ void char_charlist_notify( int fd, struct char_session_data* sd ){
WFIFOSET(fd,6); WFIFOSET(fd,6);
} }
/*
* 0x20d <PacketLength>.W <TAG_CHARACTER_BLOCK_INFO>24B (HC_BLOCK_CHARACTER)
* <GID>L <szExpireDate>20B (TAG_CHARACTER_BLOCK_INFO)
*/
void char_block_character( int fd, struct char_session_data* sd ){ void char_block_character( int fd, struct char_session_data* sd ){
WFIFOHEAD(fd, 4); int i=0, len=4;
WFIFOW(fd, 0) = 0x20d; char szExpireDate[20];
WFIFOW(fd, 2) = 4; //packet len time_t now = time(NULL);
WFIFOSET(fd,4);
ARR_FIND(0, MAX_CHARS, i, sd->unban_time[i] > now); //should we use MAX_CHARS or sd->charslot
if(i < MAX_CHARS){
memset(szExpireDate,'\0',20);
WFIFOHEAD(fd, 4+MAX_CHARS*24);
WFIFOW(fd, 0) = 0x20d;
for(i=0; i<MAX_CHARS; i++){
if( sd->unban_time[i] > now ) {
WFIFOL(fd, 4+i*24) = sd->found_char[i]; //gid
timestamp2string(szExpireDate, 20, sd->unban_time[i], "%Y-%m-%d %H:%M:%S");
memcpy(WFIFOP(fd,8+i*24),szExpireDate,20);
len+=24;
}
}
WFIFOW(fd, 2) = len; //packet len
WFIFOSET(fd,len);
}
} }
void mmo_char_send099d(int fd, struct char_session_data *sd) { void mmo_char_send099d(int fd, struct char_session_data *sd) {
@ -2034,7 +2059,9 @@ void mmo_char_send(int fd, struct char_session_data* sd){
char_charlist_notify(fd,sd); char_charlist_notify(fd,sd);
char_block_character(fd,sd); char_block_character(fd,sd);
} }
else mmo_char_send006b(fd,sd); //else
//@FIXME dump from kro doesn't show 6b transmission
mmo_char_send006b(fd,sd);
} }
int char_married(int pl1, int pl2) int char_married(int pl1, int pl2)
@ -2965,7 +2992,141 @@ void mapif_on_disconnect(int id)
ShowStatus("Map-server #%d has disconnected.\n", id); ShowStatus("Map-server #%d has disconnected.\n", id);
mapif_server_reset(id); mapif_server_reset(id);
} }
/**
* Request from map-server to change an account's status (will just be forwarded to login server)
* ZH 2b0e <aid>L <charname>24B <opetype>W <timediff>L
* @param fd: link to mapserv
*/
int mapif_parse_req_alter_acc(int fd){
if (RFIFOREST(fd) < 36)
return 0;
else {
int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline
char esc_name[NAME_LENGTH*2+1];
int acc = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request)
const char* name = (char*)RFIFOP(fd,6); // name of the target character
int operation = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban, 5 changesex, 6 charban, 7 charunban
int timediff = RFIFOL(fd,32);
RFIFOSKIP(fd,36);
Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
Sql_ShowDebug(sql_handle);
else if( Sql_NumRows(sql_handle) == 0 ){
result = 1; // 1-player not found
}
else if( SQL_SUCCESS != Sql_NextRow(sql_handle) ){
Sql_ShowDebug(sql_handle);
result = 1;
} else {
char name[NAME_LENGTH];
int account_id, char_id;
char* data;
time_t unban_time;
Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
Sql_GetData(sql_handle, 2, &data, NULL); char_id = atoi(data);
Sql_GetData(sql_handle, 3, &data, NULL); unban_time = atol(data);;
Sql_FreeResult(sql_handle);
if(operation!=6 && operation!=7 && login_fd <= 0 ) //6-7 operation doesn't send to login
result = 3; // 3-login-server offline
//FIXME: need to move this check to login server [ultramage]
// if( acc != -1 && isGM(acc) < isGM(account_id) )
// result = 2; // 2-gm level too low
else
switch( operation ) {
case 1: // block
WFIFOHEAD(login_fd,10);
WFIFOW(login_fd,0) = 0x2724;
WFIFOL(login_fd,2) = account_id;
WFIFOL(login_fd,6) = 5; // new account status
WFIFOSET(login_fd,10);
break;
case 2: // ban
WFIFOHEAD(login_fd,10);
WFIFOW(login_fd, 0) = 0x2725;
WFIFOL(login_fd, 2) = account_id;
WFIFOL(login_fd, 6) = timediff;
WFIFOSET(login_fd,10);
break;
case 3: // unblock
WFIFOHEAD(login_fd,10);
WFIFOW(login_fd,0) = 0x2724;
WFIFOL(login_fd,2) = account_id;
WFIFOL(login_fd,6) = 0; // new account status
WFIFOSET(login_fd,10);
break;
case 4: // unban
WFIFOHEAD(login_fd,6);
WFIFOW(login_fd,0) = 0x272a;
WFIFOL(login_fd,2) = account_id;
WFIFOSET(login_fd,6);
break;
case 5: // changesex
WFIFOHEAD(login_fd,6);
WFIFOW(login_fd,0) = 0x2727;
WFIFOL(login_fd,2) = account_id;
WFIFOSET(login_fd,6);
break;
case 6: //charban /* handled by char server, so no redirection */
if(timediff<0 && unban_time==0) break; //attemp to reduce time of a non banned account ?!?
else if(unban_time==0) unban_time=time(NULL); //new entry
unban_time += timediff;
// condition applies; send to all map-servers to disconnect the player
if( unban_time > time(NULL) ) {
unsigned char buf[11];
SqlStmt* stmt = SqlStmt_Malloc(sql_handle);
if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
"UPDATE `%s` SET `unban_time` = ? WHERE `char_id` = ? LIMIT 1",
char_db)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_LONG, (void*)&unban_time, sizeof(unban_time))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_INT, (void*)&char_id, sizeof(char_id))
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
result=1;
}
else {
WBUFW(buf,0) = 0x2b14;
WBUFL(buf,2) = account_id;
WBUFB(buf,6) = 2;
WBUFL(buf,7) = (unsigned int)unban_time;
mapif_sendall(buf, 11);
// disconnect player if online on char-server
disconnect_player(account_id);
result=4;
}
SqlStmt_Free(stmt);
}
break;
case 7: //char unban
/* handled by char server, so no redirection */
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `unban_time` = '0' WHERE `char_id` = '%d' LIMIT 1", char_db, char_id) ) {
Sql_ShowDebug(sql_handle);
result = 1;
} else result=4;
break;
} //end switch operation
}
// send answer if a player ask, not if the server ask
if( acc != -1 && operation != 5) { // Don't send answer for changesex
WFIFOHEAD(fd,34);
WFIFOW(fd, 0) = 0x2b0f;
WFIFOL(fd, 2) = acc;
safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH);
WFIFOW(fd,30) = operation;
WFIFOW(fd,32) = result;
WFIFOSET(fd,34);
}
}
return 1;
}
int parse_frommap(int fd) int parse_frommap(int fd)
{ {
@ -3381,108 +3542,7 @@ int parse_frommap(int fd)
RFIFOSKIP(fd, 86); RFIFOSKIP(fd, 86);
break; break;
case 0x2b0e: // Request from map-server to change an account's status (will just be forwarded to login server) case 0x2b0e: mapif_parse_req_alter_acc(fd); break;
if (RFIFOREST(fd) < 44)
return 0;
{
int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline
char esc_name[NAME_LENGTH*2+1];
int acc = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request)
const char* name = (char*)RFIFOP(fd,6); // name of the target character
int type = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban
short year = RFIFOW(fd,32);
short month = RFIFOW(fd,34);
short day = RFIFOW(fd,36);
short hour = RFIFOW(fd,38);
short minute = RFIFOW(fd,40);
short second = RFIFOW(fd,42);
RFIFOSKIP(fd,44);
Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
Sql_ShowDebug(sql_handle);
else
if( Sql_NumRows(sql_handle) == 0 )
{
result = 1; // 1-player not found
}
else
if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
Sql_ShowDebug(sql_handle);
//FIXME: set proper result value?
else
{
char name[NAME_LENGTH];
int account_id;
char* data;
Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
if( login_fd <= 0 )
result = 3; // 3-login-server offline
//FIXME: need to move this check to login server [ultramage]
// else
// if( acc != -1 && isGM(acc) < isGM(account_id) )
// result = 2; // 2-gm level too low
else
switch( type ) {
case 1: // block
WFIFOHEAD(login_fd,10);
WFIFOW(login_fd,0) = 0x2724;
WFIFOL(login_fd,2) = account_id;
WFIFOL(login_fd,6) = 5; // new account status
WFIFOSET(login_fd,10);
break;
case 2: // ban
WFIFOHEAD(login_fd,18);
WFIFOW(login_fd, 0) = 0x2725;
WFIFOL(login_fd, 2) = account_id;
WFIFOW(login_fd, 6) = year;
WFIFOW(login_fd, 8) = month;
WFIFOW(login_fd,10) = day;
WFIFOW(login_fd,12) = hour;
WFIFOW(login_fd,14) = minute;
WFIFOW(login_fd,16) = second;
WFIFOSET(login_fd,18);
break;
case 3: // unblock
WFIFOHEAD(login_fd,10);
WFIFOW(login_fd,0) = 0x2724;
WFIFOL(login_fd,2) = account_id;
WFIFOL(login_fd,6) = 0; // new account status
WFIFOSET(login_fd,10);
break;
case 4: // unban
WFIFOHEAD(login_fd,6);
WFIFOW(login_fd,0) = 0x272a;
WFIFOL(login_fd,2) = account_id;
WFIFOSET(login_fd,6);
break;
case 5: // changesex
WFIFOHEAD(login_fd,6);
WFIFOW(login_fd,0) = 0x2727;
WFIFOL(login_fd,2) = account_id;
WFIFOSET(login_fd,6);
break;
}
}
Sql_FreeResult(sql_handle);
// send answer if a player ask, not if the server ask
if( acc != -1 && type != 5) { // Don't send answer for changesex
WFIFOHEAD(fd,34);
WFIFOW(fd, 0) = 0x2b0f;
WFIFOL(fd, 2) = acc;
safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH);
WFIFOW(fd,30) = type;
WFIFOW(fd,32) = result;
WFIFOSET(fd,34);
}
}
break;
case 0x2b10: // Update and send fame ranking list case 0x2b10: // Update and send fame ranking list
if (RFIFOREST(fd) < 11) if (RFIFOREST(fd) < 11)
@ -4221,6 +4281,15 @@ int parse_char(int fd)
char_id = atoi(data); char_id = atoi(data);
Sql_FreeResult(sql_handle); Sql_FreeResult(sql_handle);
/* client doesn't let it get to this point if you're banned, so its a forged packet */
if( sd->found_char[slot] == char_id && sd->unban_time[slot] > time(NULL) ) {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x6c;
WFIFOB(fd,2) = 0; // rejected from server
WFIFOSET(fd,3);
break;
}
/* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */ /* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */
set_char_online(-2,char_id,sd->account_id); set_char_online(-2,char_id,sd->account_id);

View File

@ -403,6 +403,7 @@ struct mmo_charstatus {
short rename; short rename;
time_t delete_date; time_t delete_date;
time_t unban_time;
// Char server addon system // Char server addon system
unsigned int character_moves; unsigned int character_moves;

View File

@ -6,6 +6,7 @@
#include "../common/malloc.h" #include "../common/malloc.h"
#include "../common/showmsg.h" #include "../common/showmsg.h"
#include "../common/utils.h" #include "../common/utils.h"
#include "../common/nullpo.h"
#include "timer.h" #include "timer.h"
#include <stdio.h> #include <stdio.h>
@ -406,9 +407,19 @@ unsigned long get_uptime(void)
return (unsigned long)difftime(time(NULL), start_time); return (unsigned long)difftime(time(NULL), start_time);
} }
void time2str(char *timestr, char *format, int timein) { /**
time_t timeout = time(NULL) + timein; * Converting a timestamp is a srintf according to format
strftime(timestr, 24, format, localtime(&timeout)); * safefr then strftime as it ensure \0 at end of string
* @param str, pointer to the destination string
* @param size, max length of the string
* @param timestamp, see unix epoch
* @param format, format to convert timestamp on, see strftime format
* @return the string of timestamp
*/
const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format){
size_t len = strftime(str, size, format, localtime(&timestamp));
memset(str + len, '\0', size - len);
return str;
} }
/* /*
@ -451,6 +462,8 @@ double solve_time(char* modif_p) {
time_t now = time(NULL); time_t now = time(NULL);
time_t then = now; time_t then = now;
then_tm = *localtime(&then); then_tm = *localtime(&then);
nullpo_retr(0,modif_p);
while (modif_p[0] != '\0') { while (modif_p[0] != '\0') {
value = atoi(modif_p); value = atoi(modif_p);

View File

@ -5,6 +5,7 @@
#define _TIMER_H_ #define _TIMER_H_
#include "../common/cbasetypes.h" #include "../common/cbasetypes.h"
#include <time.h>
#define DIFF_TICK(a,b) ((int)((a)-(b))) #define DIFF_TICK(a,b) ((int)((a)-(b)))
@ -50,7 +51,7 @@ int add_timer_func_list(TimerFunc func, char* name);
unsigned long get_uptime(void); unsigned long get_uptime(void);
void time2str(char* timestr, char* format, int timein); const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format);
void split_time(int time, int* year, int* month, int* day, int* hour, int* minute, int* second); void split_time(int time, int* year, int* month, int* day, int* hour, int* minute, int* second);
double solve_time(char* modif_p); double solve_time(char* modif_p);

View File

@ -297,22 +297,6 @@ bool check_password(const char* md5key, int passwdenc, const char* passwd, const
} }
/**
* Converting a timestamp is a srintf according to format
* safefr then strftime as it ensure \0 at end of string
* @param str, pointer to the destination string
* @param size, max length of the string
* @param timestamp, see unix epoch
* @param format, format to convert timestamp on, see strftime format
* @return the string of timestamp
*/
const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format){
size_t len = strftime(str, size, format, localtime(&timestamp));
memset(str + len, '\0', size - len);
return str;
}
//-------------------------------------------- //--------------------------------------------
// Test to know if an IP come from LAN or WAN. // Test to know if an IP come from LAN or WAN.
//-------------------------------------------- //--------------------------------------------
@ -766,37 +750,24 @@ int parse_fromchar(int fd){
break; break;
case 0x2725: // Receiving of map-server via char-server a ban request case 0x2725: // Receiving of map-server via char-server a ban request
if (RFIFOREST(fd) < 18) if (RFIFOREST(fd) < 10)
return 0; return 0;
else{ else{
struct mmo_account acc; struct mmo_account acc;
int account_id = RFIFOL(fd,2); int account_id = RFIFOL(fd,2);
int year = (short)RFIFOW(fd,6); int timediff = RFIFOL(fd,6);
int month = (short)RFIFOW(fd,8); RFIFOSKIP(fd,10);
int mday = (short)RFIFOW(fd,10);
int hour = (short)RFIFOW(fd,12);
int min = (short)RFIFOW(fd,14);
int sec = (short)RFIFOW(fd,16);
RFIFOSKIP(fd,18);
if( !accounts->load_num(accounts, &acc, account_id) ) if( !accounts->load_num(accounts, &acc, account_id) )
ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip); ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
else{ else{
time_t timestamp; time_t timestamp;
struct tm *tmtime;
if (acc.unban_time == 0 || acc.unban_time < time(NULL)) if (acc.unban_time == 0 || acc.unban_time < time(NULL))
timestamp = time(NULL); // new ban timestamp = time(NULL); // new ban
else else
timestamp = acc.unban_time; // add to existing ban timestamp = acc.unban_time; // add to existing ban
tmtime = localtime(&timestamp); timestamp += timediff;
tmtime->tm_year = tmtime->tm_year + year;
tmtime->tm_mon = tmtime->tm_mon + month;
tmtime->tm_mday = tmtime->tm_mday + mday;
tmtime->tm_hour = tmtime->tm_hour + hour;
tmtime->tm_min = tmtime->tm_min + min;
tmtime->tm_sec = tmtime->tm_sec + sec;
timestamp = mktime(tmtime);
if (timestamp == -1) if (timestamp == -1)
ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", server[id].name, account_id, ip); ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", server[id].name, account_id, ip);
else if( timestamp <= time(NULL) || timestamp == 0 ) else if( timestamp <= time(NULL) || timestamp == 0 )

View File

@ -2773,105 +2773,59 @@ ACMD_FUNC(char_block)
return -1; return -1;
} }
chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block chrif_ask_char_operation(sd->status.account_id, atcmd_player_name, 1, 0); // type: 1 - block
clif_displaymessage(fd, msg_txt(sd,88)); // Character name sent to char-server to ask it. clif_displaymessage(fd, msg_txt(sd,88)); // Character name sent to char-server to ask it.
return 0; return 0;
} }
/*========================================== /*==========================================
* charban command (usage: charban <time> <player_name>) * accountban command (usage: ban <%time> <player_name>)
* This command do a limited ban on a player * charban command (usage: charban <%time> <player_name>)
* Time is done as follows: * %time see common/timer.c::solve_time()
* Adjustment value (-1, 1, +1, etc...)
* Modified element:
* a or y: year
* m: month
* j or d: day
* h: hour
* mn: minute
* s: second
* <example> @ban +1m-2mn1s-6y test_player
* this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
*------------------------------------------*/ *------------------------------------------*/
ACMD_FUNC(char_ban) ACMD_FUNC(char_ban)
{ {
char * modif_p; char * modif_p;
int year, month, day, hour, minute, second, value;
time_t timestamp;
struct tm *tmtime;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
int timediff=0;
int bantype=2; //2=account block, 6=char specific
char output[256];
memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
bantype = strcmpi(command+1,"charban")?2:6; //! FIXME this breaking alias recognition
if (!message || !*message || sscanf(message, "%255s %23[^\n]", atcmd_output, atcmd_player_name) < 2) { if (!message || !*message || sscanf(message, "%255s %23[^\n]", atcmd_output, atcmd_player_name) < 2) {
clif_displaymessage(fd, msg_txt(sd,1022)); // Please enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <char name>). clif_displaymessage(fd, msg_txt(sd,1022)); // Please enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <char name>).
return -1; return -1;
} }
atcmd_output[sizeof(atcmd_output)-1] = '\0'; atcmd_output[sizeof(atcmd_output)-1] = '\0';
modif_p = atcmd_output; modif_p = atcmd_output;
year = month = day = hour = minute = second = 0; timediff = (int)solve_time(modif_p); //discard seconds
while (modif_p[0] != '\0') {
value = atoi(modif_p);
if (value == 0)
modif_p++;
else {
if (modif_p[0] == '-' || modif_p[0] == '+')
modif_p++;
while (modif_p[0] >= '0' && modif_p[0] <= '9')
modif_p++;
if (modif_p[0] == 's') {
second = value;
modif_p++;
} else if (modif_p[0] == 'n') {
minute = value;
modif_p++;
} else if (modif_p[0] == 'm' && modif_p[1] == 'n') {
minute = value;
modif_p = modif_p + 2;
} else if (modif_p[0] == 'h') {
hour = value;
modif_p++;
} else if (modif_p[0] == 'd' || modif_p[0] == 'j') {
day = value;
modif_p++;
} else if (modif_p[0] == 'm') {
month = value;
modif_p++;
} else if (modif_p[0] == 'y' || modif_p[0] == 'a') {
year = value;
modif_p++;
} else if (modif_p[0] != '\0') {
modif_p++;
}
}
}
if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) {
clif_displaymessage(fd, msg_txt(sd,85)); // Invalid time for ban command.
return -1;
}
/**
* We now check if you can adjust the ban to negative (and if this is the case)
**/
timestamp = time(NULL);
tmtime = localtime(&timestamp);
tmtime->tm_year = tmtime->tm_year + year;
tmtime->tm_mon = tmtime->tm_mon + month;
tmtime->tm_mday = tmtime->tm_mday + day;
tmtime->tm_hour = tmtime->tm_hour + hour;
tmtime->tm_min = tmtime->tm_min + minute;
tmtime->tm_sec = tmtime->tm_sec + second;
timestamp = mktime(tmtime);
if( timestamp <= time(NULL) && !pc_can_use_command(sd, "unban", COMMAND_ATCOMMAND) ) {
clif_displaymessage(fd,msg_txt(sd,1023)); // You are not allowed to reduce the length of a ban.
return -1;
}
chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 2, year, month, day, hour, minute, second); // type: 2 - ban if (timediff == 0) { //allow negative ?
clif_displaymessage(fd, msg_txt(sd,88)); // Character name sent to char-server to ask it. char output[256];
safesnprintf(output,sizeof(output),msg_txt(sd,85),bantype==6?"charban":"ban",timediff); // Invalid time for %s command (time=%d)
clif_displaymessage(fd, output);
clif_displaymessage(fd, msg_txt(sd,702)); // Time parameter format is +/-<value> to alter. y/a = Year, m = Month, d/j = Day, h = Hour, n/mn = Minute, s = Second.
return -1;
}
if( timediff<0 && (
( bantype==2 && !pc_can_use_command(sd, "unban", COMMAND_ATCOMMAND) )
|| ( bantype==6 && !pc_can_use_command(sd, "charunban", COMMAND_ATCOMMAND)) )
){
clif_displaymessage(fd,msg_txt(sd,1023)); // You are not allowed to alter the time of a ban.
return -1;
}
chrif_ask_char_operation(sd->status.account_id, atcmd_player_name, bantype, timediff); // type: 2 - ban
safesnprintf(output,sizeof(output),msg_txt(sd,88),bantype==6?"char":"login"); // Sending request to %s server...
clif_displaymessage(fd, output);
return 0; return 0;
} }
@ -2891,28 +2845,33 @@ ACMD_FUNC(char_unblock)
} }
// send answer to login server via char-server // send answer to login server via char-server
chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock chrif_ask_char_operation(sd->status.account_id, atcmd_player_name, 3, 0); // type: 3 - unblock
clif_displaymessage(fd, msg_txt(sd,88)); // Character name sent to char-server to ask it. clif_displaymessage(fd, msg_txt(sd,88)); // Character name sent to char-server to ask it.
return 0; return 0;
} }
/*========================================== /*==========================================
* charunban command (usage: charunban <player_name>) * acc unban command (usage: unban <player_name>)
* char unban command (usage: charunban <player_name>)
*------------------------------------------*/ *------------------------------------------*/
ACMD_FUNC(char_unban) ACMD_FUNC(char_unban){
{ int unbantype=4;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
unbantype = strcmpi(command+1,"charunban")?4:7; //! FIXME this breaking alias recognition
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, msg_txt(sd,1025)); // Please enter a player name (usage: @charunban <char name>). if(unbantype==4) clif_displaymessage(fd, msg_txt(sd,1025)); // Please enter a player name (usage: @unblock <char name>).
else clif_displaymessage(fd, msg_txt(sd,435)); //Please enter a player name (usage: @charunban <char name>).
return -1; return -1;
} }
ShowInfo("char_unban unbantype=%d\n",unbantype);
// send answer to login server via char-server // send answer to login server via char-server
chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban chrif_ask_char_operation(sd->status.account_id, atcmd_player_name, unbantype, 0); // type: 4 - unban
clif_displaymessage(fd, msg_txt(sd,88)); // Character name sent to char-server to ask it. clif_displaymessage(fd, msg_txt(sd,88)); // Character name sent to char-server to ask it.
return 0; return 0;
@ -4615,14 +4574,15 @@ ACMD_FUNC(unjail)
return 0; return 0;
} }
ACMD_FUNC(jailfor) ACMD_FUNC(jailfor) {
{
struct map_session_data *pl_sd = NULL; struct map_session_data *pl_sd = NULL;
char * modif_p; char * modif_p;
int jailtime = 0,x,y; int jailtime = 0,x,y;
short m_index = 0; short m_index = 0;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) { if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) {
clif_displaymessage(fd, msg_txt(sd,400)); //Usage: @jailfor <time> <character name> clif_displaymessage(fd, msg_txt(sd,400)); //Usage: @jailfor <time> <character name>
return -1; return -1;
@ -4658,13 +4618,14 @@ ACMD_FUNC(jailfor)
clif_displaymessage(fd, msg_txt(sd,121)); // Player unjailed clif_displaymessage(fd, msg_txt(sd,121)); // Player unjailed
} else { } else {
int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
char timestr[CHAT_SIZE_MAX]; char timestr[21];
time_t now=time(NULL);
split_time(jailtime*60,&year,&month,&day,&hour,&minute,&second); split_time(jailtime*60,&year,&month,&day,&hour,&minute,&second);
sprintf(atcmd_output,msg_txt(sd,402),msg_txt(sd,1137),year,month,day,hour,minute); // %s in jail for %d years, %d months, %d days, %d hours and %d minutes sprintf(atcmd_output,msg_txt(sd,402),msg_txt(sd,1137),year,month,day,hour,minute); // %s in jail for %d years, %d months, %d days, %d hours and %d minutes
clif_displaymessage(pl_sd->fd, atcmd_output); clif_displaymessage(pl_sd->fd, atcmd_output);
sprintf(atcmd_output,msg_txt(sd,402),msg_txt(sd,1138),year,month,day,hour,minute); // This player is now in jail for %d years, %d months, %d days, %d hours and %d minutes sprintf(atcmd_output,msg_txt(sd,402),msg_txt(sd,1138),year,month,day,hour,minute); // This player is now in jail for %d years, %d months, %d days, %d hours and %d minutes
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
time2str(timestr,"%Y-%m-%d %H:%M",jailtime*60); timestamp2string(timestr,20,now+jailtime*60,"%Y-%m-%d %H:%M");
sprintf(atcmd_output,"Release date is: %s",timestr); sprintf(atcmd_output,"Release date is: %s",timestr);
clif_displaymessage(pl_sd->fd, atcmd_output); clif_displaymessage(pl_sd->fd, atcmd_output);
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
@ -4693,7 +4654,8 @@ ACMD_FUNC(jailfor)
//By Coltaro //By Coltaro
ACMD_FUNC(jailtime){ ACMD_FUNC(jailtime){
int year, month, day, hour, minute, second; int year, month, day, hour, minute, second;
char timestr[CHAT_SIZE_MAX]; char timestr[21];
time_t now = time(NULL);
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
@ -4716,7 +4678,7 @@ ACMD_FUNC(jailtime){
split_time(sd->sc.data[SC_JAILED]->val1*60,&year,&month,&day,&hour,&minute,&second); split_time(sd->sc.data[SC_JAILED]->val1*60,&year,&month,&day,&hour,&minute,&second);
sprintf(atcmd_output,msg_txt(sd,402),msg_txt(sd,1142),year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes sprintf(atcmd_output,msg_txt(sd,402),msg_txt(sd,1142),year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
time2str(timestr,"%Y-%m-%d %H:%M",sd->sc.data[SC_JAILED]->val1*60); timestamp2string(timestr,20,now+sd->sc.data[SC_JAILED]->val1*60,"%Y-%m-%d %H:%M");
sprintf(atcmd_output,"Release date is: %s",timestr); sprintf(atcmd_output,"Release date is: %s",timestr);
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
@ -9189,13 +9151,14 @@ ACMD_FUNC(langtype)
} }
#ifdef VIP_ENABLE #ifdef VIP_ENABLE
ACMD_FUNC(vip) ACMD_FUNC(vip) {
{
struct map_session_data *pl_sd = NULL; struct map_session_data *pl_sd = NULL;
char * modif_p; char * modif_p;
int viptime = 0; int viptime = 0;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) { if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) {
clif_displaymessage(fd, msg_txt(sd,700)); //Usage: @vip <time> <character name> clif_displaymessage(fd, msg_txt(sd,700)); //Usage: @vip <time> <character name>
return -1; return -1;
@ -9230,13 +9193,14 @@ ACMD_FUNC(vip)
clif_displaymessage(fd, msg_txt(sd,704)); // Player is no longer VIP. clif_displaymessage(fd, msg_txt(sd,704)); // Player is no longer VIP.
} else { } else {
int year,month,day,hour,minute,second; int year,month,day,hour,minute,second;
char timestr[128]; char timestr[21];
time_t now=time(NULL);
split_time(pl_sd->vip.time*60,&year,&month,&day,&hour,&minute,&second); split_time(pl_sd->vip.time*60,&year,&month,&day,&hour,&minute,&second);
sprintf(atcmd_output,msg_txt(sd,705),pl_sd->status.name,year,month,day,hour,minute); //%s is VIP for %d years, %d months, %d days, %d hours and %d minutes. sprintf(atcmd_output,msg_txt(sd,705),pl_sd->status.name,year,month,day,hour,minute); //%s is VIP for %d years, %d months, %d days, %d hours and %d minutes.
clif_displaymessage(pl_sd->fd, atcmd_output); clif_displaymessage(pl_sd->fd, atcmd_output);
sprintf(atcmd_output,msg_txt(sd,706),year,month,day,hour,minute); //This player is now VIP for %d years, %d months, %d days, %d hours and %d minutes. sprintf(atcmd_output,msg_txt(sd,706),year,month,day,hour,minute); //This player is now VIP for %d years, %d months, %d days, %d hours and %d minutes.
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
time2str(timestr,"%Y-%m-%d %H:%M",pl_sd->vip.time*60); timestamp2string(timestr,20,now+pl_sd->vip.time*60,"%Y-%m-%d %H:%M");
sprintf(atcmd_output,"%s : %s",msg_txt(sd,707),timestr); //You are VIP until : sprintf(atcmd_output,"%s : %s",msg_txt(sd,707),timestr); //You are VIP until :
clif_displaymessage(pl_sd->fd, atcmd_output); clif_displaymessage(pl_sd->fd, atcmd_output);
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
@ -9379,6 +9343,8 @@ void atcommand_basecommands(void) {
ACMD_DEF2("ban", char_ban), ACMD_DEF2("ban", char_ban),
ACMD_DEF2("unblock", char_unblock), ACMD_DEF2("unblock", char_unblock),
ACMD_DEF2("unban", char_unban), ACMD_DEF2("unban", char_unban),
ACMD_DEF2("charban", char_ban),
ACMD_DEF2("charunban", char_unban),
ACMD_DEF2("mount", mount_peco), ACMD_DEF2("mount", mount_peco),
ACMD_DEF(guildspy), ACMD_DEF(guildspy),
ACMD_DEF(partyspy), ACMD_DEF(partyspy),

View File

@ -42,7 +42,7 @@ static DBMap* auth_db; // int id -> struct auth_node*
static const int packet_len_table[0x3d] = { // U - used, F - free static const int packet_len_table[0x3d] = { // U - used, F - free
60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff 60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
6,-1,19, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07 6,-1,19, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
6,30, 10, -1,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f 6,30, 10, -1,86, 7,36,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
11,10,10, 0,11, -1,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, U->2b15, U->2b16, U->2b17 11,10,10, 0,11, -1,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, U->2b15, U->2b16, U->2b17
2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f 2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
-1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27 -1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27
@ -814,43 +814,36 @@ int chrif_changeemail(int id, const char *actual_email, const char *new_email) {
} }
/*========================================== /*==========================================
* S 2b0e <accid>.l <name>.24B <type>.w { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } * S 2b0e <accid>.l <name>.24B <operation_type>.w <timediff>L
* Send an account modification request to the login server (via char server). * Send an account modification request to the login server (via char server).
* type of operation: * type of operation:
* 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex (use next function for 5) * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex (use next function for 5), 6: charban, 7: charunban
*------------------------------------------*/ *------------------------------------------*/
int chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second) { int chrif_ask_char_operation(int acc, const char* character_name, unsigned short operation_type, int timediff) {
chrif_check(-1); chrif_check(-1);
WFIFOHEAD(char_fd,44); WFIFOHEAD(char_fd,36);
WFIFOW(char_fd,0) = 0x2b0e; WFIFOW(char_fd,0) = 0x2b0e;
WFIFOL(char_fd,2) = acc; WFIFOL(char_fd,2) = acc;
safestrncpy((char*)WFIFOP(char_fd,6), character_name, NAME_LENGTH); safestrncpy((char*)WFIFOP(char_fd,6), character_name, NAME_LENGTH);
WFIFOW(char_fd,30) = operation_type; WFIFOW(char_fd,30) = operation_type;
if ( operation_type == 2 ) { if ( operation_type == 2 || operation_type == 6)
WFIFOW(char_fd,32) = year; WFIFOL(char_fd,32) = timediff;
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;
}
WFIFOSET(char_fd,44); WFIFOSET(char_fd,36);
return 0; return 0;
} }
int chrif_changesex(struct map_session_data *sd) { int chrif_changesex(struct map_session_data *sd) {
chrif_check(-1); chrif_check(-1);
WFIFOHEAD(char_fd,44); WFIFOHEAD(char_fd,36);
WFIFOW(char_fd,0) = 0x2b0e; WFIFOW(char_fd,0) = 0x2b0e;
WFIFOL(char_fd,2) = sd->status.account_id; WFIFOL(char_fd,2) = sd->status.account_id;
safestrncpy((char*)WFIFOP(char_fd,6), sd->status.name, NAME_LENGTH); safestrncpy((char*)WFIFOP(char_fd,6), sd->status.name, NAME_LENGTH);
WFIFOW(char_fd,30) = 5; WFIFOW(char_fd,30) = 5;
WFIFOSET(char_fd,44); WFIFOSET(char_fd,36);
clif_displaymessage(sd->fd, msg_txt(sd,408)); //"Need disconnection to perform change-sex request..." clif_displaymessage(sd->fd, msg_txt(sd,408)); //"Need disconnection to perform change-sex request..."
@ -865,12 +858,13 @@ int chrif_changesex(struct map_session_data *sd) {
* R 2b0f <accid>.l <name>.24B <type>.w <answer>.w * R 2b0f <accid>.l <name>.24B <type>.w <answer>.w
* Processing a reply to chrif_char_ask_name() (request to modify an account). * Processing a reply to chrif_char_ask_name() (request to modify an account).
* type of operation: * type of operation:
* 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex, 6: charban, 7: charunban
* type of answer: * type of answer:
* 0: login-server request done * 0: login-server request done
* 1: player not found * 1: player not found
* 2: gm level too low * 2: gm level too low
* 3: login-server offline * 3: login-server offline
* 4: char-server request done
*------------------------------------------*/ *------------------------------------------*/
static void chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, uint16 answer) { static void chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, uint16 answer) {
struct map_session_data* sd; struct map_session_data* sd;
@ -886,14 +880,17 @@ static void chrif_char_ask_name_answer(int acc, const char* player_name, uint16
if( type > 0 && type <= 5 ) if( type > 0 && type <= 5 )
snprintf(action,25,"%s",msg_txt(sd,427+type)); //block|ban|unblock|unban|change the sex of snprintf(action,25,"%s",msg_txt(sd,427+type)); //block|ban|unblock|unban|change the sex of
else if( type==6) snprintf(action,25,"%s","charban"); //TODO make some place for those type in msg_conf
else if( type==7) snprintf(action,25,"%s","charunban");
else else
snprintf(action,25,"???"); snprintf(action,25,"???");
switch( answer ) { switch( answer ) {
case 0 : sprintf(output, msg_txt(sd,424), action, NAME_LENGTH, player_name); break; case 0 : sprintf(output, msg_txt(sd,424), "login-serv", action, NAME_LENGTH, player_name); break; //%s has been asked to %s the player '%.*s'.
case 1 : sprintf(output, msg_txt(sd,425), NAME_LENGTH, player_name); break; case 1 : sprintf(output, msg_txt(sd,425), NAME_LENGTH, player_name); break;
case 2 : sprintf(output, msg_txt(sd,426), action, NAME_LENGTH, player_name); break; case 2 : sprintf(output, msg_txt(sd,426), action, NAME_LENGTH, player_name); break;
case 3 : sprintf(output, msg_txt(sd,427), action, NAME_LENGTH, player_name); break; case 3 : sprintf(output, msg_txt(sd,427), action, NAME_LENGTH, player_name); break;
case 4 : sprintf(output, msg_txt(sd,424), "char-serv", action, NAME_LENGTH, player_name); break;
default: output[0] = '\0'; break; default: output[0] = '\0'; break;
} }
@ -1026,10 +1023,11 @@ int chrif_deadopt(int father_id, int mother_id, int child_id) {
* Disconnection of a player (account has been banned of has a status, from login-server) by [Yor] * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
*------------------------------------------*/ *------------------------------------------*/
int chrif_accountban(int fd) { int chrif_accountban(int fd) {
int acc; int acc, res=0;
struct map_session_data *sd; struct map_session_data *sd;
acc = RFIFOL(fd,2); acc = RFIFOL(fd,2);
res = RFIFOB(fd,6); // 0: change of statut, 1: ban, 2 charban
if ( battle_config.etc_log ) if ( battle_config.etc_log )
ShowNotice("chrif_accountban %d.\n", acc); ShowNotice("chrif_accountban %d.\n", acc);
@ -1042,7 +1040,7 @@ int chrif_accountban(int fd) {
} }
sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters 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 if (res == 0) {
int ret_status = RFIFOL(fd,7); // status or final date of a banishment int ret_status = RFIFOL(fd,7); // status or final date of a banishment
if(0<ret_status && ret_status<=9) if(0<ret_status && ret_status<=9)
clif_displaymessage(sd->fd, msg_txt(sd,411+ret_status)); clif_displaymessage(sd->fd, msg_txt(sd,411+ret_status));
@ -1050,12 +1048,13 @@ int chrif_accountban(int fd) {
clif_displaymessage(sd->fd, msg_txt(sd,421)); clif_displaymessage(sd->fd, msg_txt(sd,421));
else else
clif_displaymessage(sd->fd, msg_txt(sd,420)); //"Your account has not more authorised." clif_displaymessage(sd->fd, msg_txt(sd,420)); //"Your account has not more authorised."
} else if (RFIFOB(fd,6) == 1) { // 0: change of statut, 1: ban } else if (res == 1 || res == 2) {
time_t timestamp; time_t timestamp;
char tmpstr[2048]; char tmpstr[256];
char strtime[25];
timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment
strcpy(tmpstr, msg_txt(sd,423)); //"Your account has been banished until " strftime(strtime, 24, "%d-%m-%Y %H:%M:%S", localtime(&timestamp));
strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(&timestamp)); safesnprintf(tmpstr,sizeof(tmpstr),msg_txt(sd,423),res==2?"char":"account",strtime); //"Your %s has been banished until %s "
clif_displaymessage(sd->fd, tmpstr); clif_displaymessage(sd->fd, tmpstr);
} }

View File

@ -50,7 +50,7 @@ int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port);
int chrif_searchcharid(int char_id); int chrif_searchcharid(int char_id);
int chrif_changeemail(int id, const char *actual_email, const char *new_email); int chrif_changeemail(int id, const char *actual_email, const char *new_email);
int chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second); int chrif_ask_char_operation(int acc, const char* character_name, unsigned short operation_type, int timediff);
int chrif_updatefamelist(struct map_session_data *sd); int chrif_updatefamelist(struct map_session_data *sd);
int chrif_buildfamelist(void); int chrif_buildfamelist(void);
int chrif_save_scdata(struct map_session_data *sd); int chrif_save_scdata(struct map_session_data *sd);

View File

@ -207,13 +207,13 @@ int impossible_trade_check(struct map_session_data *sd)
intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
// if we block people // if we block people
if (battle_config.ban_hack_trade < 0) { if (battle_config.ban_hack_trade < 0) {
chrif_char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block chrif_ask_char_operation(-1, sd->status.name, 1, 0); // type: 1 - block
set_eof(sd->fd); // forced to disconnect because of the hack set_eof(sd->fd); // forced to disconnect because of the hack
// message about the ban // message about the ban
strcpy(message_to_gm, msg_txt(sd,540)); // This player has been definitively blocked. strcpy(message_to_gm, msg_txt(sd,540)); // This player has been definitively blocked.
// if we ban people // if we ban people
} else if (battle_config.ban_hack_trade > 0) { } else if (battle_config.ban_hack_trade > 0) {
chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second) chrif_ask_char_operation(-1, sd->status.name, 2, battle_config.ban_hack_trade*60); // type: 2 - ban (year, month, day, hour, minute, second)
set_eof(sd->fd); // forced to disconnect because of the hack set_eof(sd->fd); // forced to disconnect because of the hack
// message about the ban // message about the ban
sprintf(message_to_gm, msg_txt(sd,507), battle_config.ban_hack_trade); // This player has been banned for %d minute(s). sprintf(message_to_gm, msg_txt(sd,507), battle_config.ban_hack_trade); // This player has been banned for %d minute(s).