Skip to content
Permalink
Browse files

Added int64 support to the script engine (#4522)

Added support for signed 64 bit integer value computation into the script engine.
This is required because newer official features require support for bigger numbers inside the scripts.

This also cleans up a lot of messy code and fixes a few issues like script stack corruptions.

Thanks to @aleos89 and everyone who supported me with this.
  • Loading branch information
Lemongrass3110 committed Jan 13, 2020
1 parent 3142863 commit e72c7360cf9108b9aa5b5ad7891f8a8dcf16af49
@@ -1525,7 +1525,7 @@
1370: Usage: ex. "@set PoringCharVarSTR$" outputs its value, Super Duper String.
1371: NPC variables may not be used with @set.
1372: Instance variables may not be used with @set.
1373: %s value is now: %d
1373: %s value is now: %lld
1374: %s value is now: %s
1375: %s is blank.

@@ -1341,8 +1341,8 @@
1370: 用法: ex. "@set PoringCharVarSTR$" outputs its value, Super Duper String.
1371: NPC variables may not be used with @set.
1372: Instance variables may not be used with @set.
1373: %s value is now :%d
1374: %s value is now :%s
1373: %s value is now: %lld
1374: %s value is now: %s
1375: %s is empty
//1376: free

@@ -1354,8 +1354,8 @@
1370: Usage: ex. "@set PoringCharVarSTR$" affiche sa valeur actuelle, Super Duper String.
1371: Les variables des NPC ne peuvent pas �tre utilis�es/chang�es avec @set.
1372: Les variables d'Instance ne peuvent pas �tre utilis�es avec @set.
1373: %s valeur est maintenant :%d
1374: %s valeur est maintenant :%s
1373: %s valeur est maintenant: %lld
1374: %s valeur est maintenant: %s
1375: %s est vide
//1376: free

@@ -1445,7 +1445,7 @@
1370: Contoh penggunaan: \"@set PoringCharVarSTR$\" menampilkan nilainya, Super Duper String.
1371: Variabel pada NPC tidak boleh digunakan dengan @set.
1372: Variabel instansi tidak boleh digunakan dengan @set.
1373: Nilai %s saat ini: %d
1373: Nilai %s saat ini: %lld
1374: Nilai %s saat ini: %s
1375: %s kosong
//1376: free
@@ -1524,8 +1524,8 @@
1370: Uso: ex. "@set PoringCharVarSTR$" exibe seu valor, Super Duper String.
1371: Variáveis de NPC não podem ser usadas com @set.
1372: Variáveis de instância não podem ser usadas com @set.
1373: %s valor agora é :%d
1374: %s valor agora é :%s
1373: %s valor agora é: %lld
1374: %s valor agora é: %s
1375: %s é vazia
//1376: free

@@ -1354,8 +1354,8 @@
1370: �������������: ����. "@set PoringCharVarSTR$" ����� ����� �������� "Super Duper String".
1371: ���������� ��� �� ����� ���� ������������ �������� @set.
1372: ���������� ����� �� ����� ���� ������������ �������� @set.
1373: %s �������� :%d
1374: %s �������� :%s
1373: %s ��������: %lld
1374: %s ��������: %s
1375: %s �����
//1376: free

@@ -1493,7 +1493,7 @@
1370: Instrucciones: ej. "@set PoringCharVarSTR$" muestra su valor, cadena de texto.
1371: Las variables de NPC no se pueden editar con @set.
1372: Las variables de instancias no se pueden editar con @set.
1373: El valor %s ahora es: %d
1373: El valor %s ahora es: %lld
1374: El valor %s�ahora es: %s
1375: %s est� vac�o

@@ -1347,7 +1347,7 @@
1370: �Ը���: ex. "@set PoringCharVarSTR$" ���ʴ����Ѿ���繤��, Super Duper String.
1371: ����� NPC �������ö��駤������� @set ��.
1372: ����� Instance �������ö��駤������� @set ��.
1373: %s �դ��: %d
1373: %s �դ��: %lld
1374: %s �դ��: %s
1375: %s ����դ����.
//1376: free
@@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS `acc_reg_num` (
`account_id` int(11) unsigned NOT NULL default '0',
`key` varchar(32) binary NOT NULL default '',
`index` int(11) unsigned NOT NULL default '0',
`value` int(11) NOT NULL default '0',
`value` bigint(11) NOT NULL default '0',
PRIMARY KEY (`account_id`,`key`,`index`),
KEY `account_id` (`account_id`)
) ENGINE=MyISAM;
@@ -274,7 +274,7 @@ CREATE TABLE IF NOT EXISTS `char_reg_num` (
`char_id` int(11) unsigned NOT NULL default '0',
`key` varchar(32) binary NOT NULL default '',
`index` int(11) unsigned NOT NULL default '0',
`value` int(11) NOT NULL default '0',
`value` bigint(11) NOT NULL default '0',
PRIMARY KEY (`char_id`,`key`,`index`),
KEY `char_id` (`char_id`)
) ENGINE=MyISAM;
@@ -403,7 +403,7 @@ CREATE TABLE IF NOT EXISTS `global_acc_reg_num` (
`account_id` int(11) unsigned NOT NULL default '0',
`key` varchar(32) binary NOT NULL default '',
`index` int(11) unsigned NOT NULL default '0',
`value` int(11) NOT NULL default '0',
`value` bigint(11) NOT NULL default '0',
PRIMARY KEY (`account_id`,`key`,`index`),
KEY `account_id` (`account_id`)
) ENGINE=MyISAM;
@@ -0,0 +1,8 @@
ALTER TABLE `acc_reg_num`
MODIFY `value` bigint(11) NOT NULL default '0';

ALTER TABLE `global_acc_reg_num`
MODIFY `value` bigint(11) NOT NULL default '0';

ALTER TABLE `char_reg_num`
MODIFY `value` bigint(11) NOT NULL default '0';
@@ -178,7 +178,7 @@ void chlogif_prepsend_global_accreg(void) {
}
}

void chlogif_send_global_accreg(const char *key, unsigned int index, intptr_t val, bool is_string) {
void chlogif_send_global_accreg(const char *key, unsigned int index, int64 int_value, const char* string_value, bool is_string) {
int nlen = WFIFOW(login_fd, 2);
size_t len;

@@ -197,26 +197,25 @@ void chlogif_send_global_accreg(const char *key, unsigned int index, intptr_t va
nlen += 4;

if( is_string ) {
WFIFOB(login_fd, nlen) = val ? 2 : 3;
WFIFOB(login_fd, nlen) = string_value ? 2 : 3;
nlen += 1;

if( val ) {
char *sval = (char*)val;
len = strlen(sval)+1;
if( string_value ) {
len = strlen(string_value)+1;

WFIFOB(login_fd, nlen) = (unsigned char)len; // won't be higher; the column size is 254
nlen += 1;

safestrncpy(WFIFOCP(login_fd,nlen), sval, len);
safestrncpy(WFIFOCP(login_fd,nlen), string_value, len);
nlen += len;
}
} else {
WFIFOB(login_fd, nlen) = val ? 0 : 1;
WFIFOB(login_fd, nlen) = int_value ? 0 : 1;
nlen += 1;

if( val ) {
WFIFOL(login_fd, nlen) = (int)val;
nlen += 4;
if( int_value ) {
WFIFOQ(login_fd, nlen) = int_value;
nlen += 8;
}
}

@@ -19,7 +19,7 @@ TIMER_FUNC(chlogif_broadcast_user_count);
void chlogif_send_usercount(int users);
void chlogif_upd_global_accreg(uint32 account_id, uint32 char_id);
void chlogif_prepsend_global_accreg(void);
void chlogif_send_global_accreg(const char *key, unsigned int index, intptr_t val, bool is_string);
void chlogif_send_global_accreg(const char *key, unsigned int index, int64 int_value, const char* string_value, bool is_string);
void chlogif_request_accreg2(uint32 account_id, uint32 char_id);
void chlogif_send_reqaccdata(int fd, struct char_session_data *sd);
void chlogif_send_setacconline(int aid);
@@ -561,54 +561,54 @@ void mapif_accinfo_ack(bool success, int map_fd, int u_fd, int u_aid, int accoun
* @param val either str or int, depending on type
* @param type false when int, true otherwise
**/
void inter_savereg(uint32 account_id, uint32 char_id, const char *key, unsigned int index, intptr_t val, bool is_string)
void inter_savereg(uint32 account_id, uint32 char_id, const char *key, uint32 index, int64 int_value, const char* string_value, bool is_string)
{
char esc_val[254*2+1];
char esc_key[32*2+1];

Sql_EscapeString(sql_handle, esc_key, key);
if( is_string && val ) {
Sql_EscapeString(sql_handle, esc_val, (char*)val);
if( is_string && string_value ) {
Sql_EscapeString(sql_handle, esc_val, string_value);
}
if( key[0] == '#' && key[1] == '#' ) { // global account reg
if( session_isValid(login_fd) )
chlogif_send_global_accreg(key,index,val,is_string);
chlogif_send_global_accreg( key, index, int_value, string_value, is_string );
else {
ShowError("Login server unavailable, can't perform update on '%s' variable for AID:%d CID:%d\n",key,account_id,char_id);
ShowError("Login server unavailable, can't perform update on '%s' variable for AID:%" PRIu32 " CID:%" PRIu32 "\n",key,account_id,char_id);
}
} else if ( key[0] == '#' ) { // local account reg
if( is_string ) {
if( val ) {
if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%s')", schema_config.acc_reg_str_table, account_id, esc_key, index, esc_val) )
if( string_value ) {
if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%" PRIu32 "','%s','%" PRIu32 "','%s')", schema_config.acc_reg_str_table, account_id, esc_key, index, esc_val) )
Sql_ShowDebug(sql_handle);
} else {
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.acc_reg_str_table, account_id, esc_key, index) )
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%" PRIu32 "' AND `key` = '%s' AND `index` = '%" PRIu32 "' LIMIT 1", schema_config.acc_reg_str_table, account_id, esc_key, index) )
Sql_ShowDebug(sql_handle);
}
} else {
if( val ) {
if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%d')", schema_config.acc_reg_num_table, account_id, esc_key, index, (int)val) )
if( int_value ) {
if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%" PRIu32 "','%s','%" PRIu32 "','%" PRId64 "')", schema_config.acc_reg_num_table, account_id, esc_key, index, int_value) )
Sql_ShowDebug(sql_handle);
} else {
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.acc_reg_num_table, account_id, esc_key, index) )
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%" PRIu32 "' AND `key` = '%s' AND `index` = '%" PRIu32 "' LIMIT 1", schema_config.acc_reg_num_table, account_id, esc_key, index) )
Sql_ShowDebug(sql_handle);
}
}
} else { /* char reg */
if( is_string ) {
if( val ) {
if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%s')", schema_config.char_reg_str_table, char_id, esc_key, index, esc_val) )
if( string_value ) {
if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%" PRIu32 "','%s','%" PRIu32 "','%s')", schema_config.char_reg_str_table, char_id, esc_key, index, esc_val) )
Sql_ShowDebug(sql_handle);
} else {
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.char_reg_str_table, char_id, esc_key, index) )
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%" PRIu32 "' AND `key` = '%s' AND `index` = '%" PRIu32 "' LIMIT 1", schema_config.char_reg_str_table, char_id, esc_key, index) )
Sql_ShowDebug(sql_handle);
}
} else {
if( val ) {
if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%d')", schema_config.char_reg_num_table, char_id, esc_key, index, (int)val) )
if( int_value ) {
if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%" PRIu32 "','%s','%" PRIu32 "','%" PRId64 "')", schema_config.char_reg_num_table, char_id, esc_key, index, int_value) )
Sql_ShowDebug(sql_handle);
} else {
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.char_reg_num_table, char_id, esc_key, index) )
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%" PRIu32 "' AND `key` = '%s' AND `index` = '%" PRIu32 "' LIMIT 1", schema_config.char_reg_num_table, char_id, esc_key, index) )
Sql_ShowDebug(sql_handle);
}
}
@@ -624,11 +624,11 @@ int inter_accreg_fromsql(uint32 account_id, uint32 char_id, int fd, int type)

switch( type ) {
case 3: //char reg
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%d'", schema_config.char_reg_str_table, char_id) )
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%" PRIu32 "'", schema_config.char_reg_str_table, char_id) )
Sql_ShowDebug(sql_handle);
break;
case 2: //account reg
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", schema_config.acc_reg_str_table, account_id) )
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%" PRIu32 "'", schema_config.acc_reg_str_table, account_id) )
Sql_ShowDebug(sql_handle);
break;
case 1: //account2 reg
@@ -667,7 +667,7 @@ int inter_accreg_fromsql(uint32 account_id, uint32 char_id, int fd, int type)

Sql_GetData(sql_handle, 1, &data, NULL);

WFIFOL(fd, plen) = (unsigned int)atol(data);
WFIFOL(fd, plen) = (uint32)atol(data);
plen += 4;

Sql_GetData(sql_handle, 2, &data, NULL);
@@ -705,11 +705,11 @@ int inter_accreg_fromsql(uint32 account_id, uint32 char_id, int fd, int type)

switch( type ) {
case 3: //char reg
if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%d'", schema_config.char_reg_num_table, char_id))
if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%" PRIu32 "'", schema_config.char_reg_num_table, char_id))
Sql_ShowDebug(sql_handle);
break;
case 2: //account reg
if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", schema_config.acc_reg_num_table, account_id))
if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%" PRIu32 "'", schema_config.acc_reg_num_table, account_id))
Sql_ShowDebug(sql_handle);
break;
#if 0 // This is already checked above.
@@ -747,13 +747,13 @@ int inter_accreg_fromsql(uint32 account_id, uint32 char_id, int fd, int type)

Sql_GetData(sql_handle, 1, &data, NULL);

WFIFOL(fd, plen) = (unsigned int)atol(data);
WFIFOL(fd, plen) = (uint32)atol(data);
plen += 4;

Sql_GetData(sql_handle, 2, &data, NULL);

WFIFOL(fd, plen) = atoi(data);
plen += 4;
WFIFOQ(fd, plen) = strtoll(data,NULL,10);
plen += 8;

WFIFOW(fd, 14) += 1;

@@ -1258,7 +1258,8 @@ int mapif_parse_WisToGM(int fd)
// Save account_reg into sql (type=2)
int mapif_parse_Registry(int fd)
{
int account_id = RFIFOL(fd, 4), char_id = RFIFOL(fd, 8), count = RFIFOW(fd, 12);
uint32 account_id = RFIFOL(fd, 4), char_id = RFIFOL(fd, 8);
uint16 count = RFIFOW(fd, 12);

if( count ) {
int cursor = 14, i;
@@ -1273,20 +1274,17 @@ int mapif_parse_Registry(int fd)
std::string key( src_key, lenkey );
cursor += lenkey + 1;

unsigned int index = RFIFOL(fd, cursor);
uint32 index = RFIFOL(fd, cursor);
cursor += 4;

switch (RFIFOB(fd, cursor++)) {
// int
case 0:
{
intptr_t lVal = RFIFOL( fd, cursor );
inter_savereg( account_id, char_id, key.c_str(), index, lVal, false );
cursor += 4;
inter_savereg( account_id, char_id, key.c_str(), index, RFIFOQ( fd, cursor ), nullptr, false );
cursor += 8;
break;
}
case 1:
inter_savereg(account_id,char_id,key.c_str(),index,0,false);
inter_savereg( account_id, char_id, key.c_str(), index, 0, nullptr, false );
break;
// str
case 2:
@@ -1295,11 +1293,11 @@ int mapif_parse_Registry(int fd)
const char* src_val= RFIFOCP(fd, cursor + 1);
std::string sval( src_val, len_val );
cursor += len_val + 1;
inter_savereg( account_id, char_id, key.c_str(), index, (intptr_t)sval.c_str(), true );
inter_savereg( account_id, char_id, key.c_str(), index, 0, sval.c_str(), true );
break;
}
case 3:
inter_savereg(account_id,char_id,key.c_str(),index,0,true);
inter_savereg( account_id, char_id, key.c_str(), index, 0, nullptr, true );
break;
default:
ShowError("mapif_parse_Registry: unknown type %d\n",RFIFOB(fd, cursor - 1));
@@ -42,7 +42,6 @@ extern unsigned int party_share_level;
extern Sql* sql_handle;
extern Sql* lsql_handle;

void inter_savereg(uint32 account_id, uint32 char_id, const char *key, unsigned int index, intptr_t val, bool is_string);
int inter_accreg_fromsql(uint32 account_id, uint32 char_id, int fd, int type);

#endif /* INTER_HPP */
@@ -2707,6 +2707,22 @@ DBData db_ptr2data(void *data)
return ret;
}

/**
* Manual cast from 'int' to the struct DBData.
* @param data Data to be casted
* @return The data as a DBData struct
* @public
*/
DBData db_i642data(int64 data)
{
DBData ret;

DB_COUNTSTAT(db_i2data);
ret.type = DB_DATA_I64;
ret.u.i64 = data;
return ret;
}

/**
* Gets int type data from struct DBData.
* If data is not int type, returns 0.
@@ -2752,6 +2768,21 @@ void* db_data2ptr(DBData *data)
return NULL;
}

/**
* Gets int64 type data from struct DBData.
* If data is not int64 type, returns 0.
* @param data Data
* @return Integer(64-bit signed) value of the data.
* @public
*/
int64 db_data2i64(DBData *data)
{
DB_COUNTSTAT(db_data2i64);
if (data && DB_DATA_I64 == data->type)
return data->u.i64;
return 0;
}

/**
* Initializes the database system.
* @public

2 comments on commit e72c736

@mazvi

This comment has been minimized.

Copy link
Contributor

mazvi replied Jan 13, 2020

Bigint 11 on sql? Why not 20?

@Atemo

This comment has been minimized.

Copy link
Contributor

Atemo replied Jan 13, 2020

11 or 20 doesn't change anything here

Please sign in to comment.
You can’t perform that action at this time.