- Merged and completed Latio's work on server-side hot-key saving (http://www.eathena.ws/board/index.php?s=&showtopic=159388&view=findpost&p=884453)

- Now hotkeys are stored server-side (table hotkey in SQL servers, file save/hotkeys.txt for TXT servers). You can disable this behaviour by commenting out the 'HOTKEY_SAVING' define in mmo.h
- Fixed a few compilation warnings/errors.
- Apply upgrade_svn11018.sql to create the hotkey table.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11019 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
skotlex 2007-08-15 22:08:30 +00:00
parent efff167bc0
commit dff80559d4
12 changed files with 219 additions and 7 deletions

View File

@ -4,6 +4,12 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/08/15
* Merged and completed Latio's work on server-side hot-key saving
(http://www.eathena.ws/board/index.php?s=&showtopic=159388&view=findpost&p=884453):
Now hotkeys are stored server-side (table hotkey in SQL servers, file
save/hotkeys.txt for TXT servers). You can disable this behaviour by
commenting out the 'HOTKEY_SAVING' define in mmo.h
* Apply upgrade_svn11018.sql to create the hotkey table. [Skotlex]
* Some serious code cleanups
- adjusted @reloadbattleconf to not depend on variable ordering
- changed all battle vars to 'int' (removes pointless duplicit coding)

View File

@ -8,6 +8,9 @@ storage_txt: save/storage.txt
// Party flatfile database, for party names, members and other party info.
party_txt: save/party.txt
// Hotkeys flatfile database, where character skill shortcuts are stored.
hotkeys_txt: save/hotkeys.txt
// Guild flatfile database, for guild names, members, and other guild info.
guild_txt: save/guild.txt
@ -114,6 +117,7 @@ loginlog_db: loginlog
// Character Database Tables
char_db: char
hotkey_db: hotkey
scdata_db: sc_data
cart_db: cart_inventory
inventory_db: inventory

View File

@ -1014,7 +1014,7 @@ packet_ver: 22
0x02b7,10
0x02b8,22
0x02b9,191
0x02ba,11
0x02ba,11,hotkey,2:4:5:9
0x02bb,8
0x02bc,6

View File

@ -116,6 +116,21 @@ CREATE TABLE `friends` (
KEY `char_id` (`char_id`)
) TYPE=MyISAM;
--
-- Table structure for table `hotkey`
--
DROP TABLE IF EXISTS `hotkey`;
CREATE TABLE `hotkey` (
`char_id` INT(11) NOT NULL,
`hotkey` TINYINT(2) unsigned NOT NULL,
`type` TINYINT(1) unsigned NOT NULL default '0',
`itemskill_id` INT(11) unsigned NOT NULL default '0',
`skill_lvl` TINYINT(4) unsigned NOT NULL default '0',
PRIMARY KEY (`char_id`,`hotkey`),
INDEX (`char_id`)
) TYPE=MYISAM;
--
-- Table structure for table `global_reg_value`
--

View File

@ -0,0 +1,10 @@
DROP TABLE IF EXISTS `hotkey`;
CREATE TABLE `hotkey` (
`char_id` INT(11) NOT NULL,
`hotkey` TINYINT(2) unsigned NOT NULL,
`type` TINYINT(1) unsigned NOT NULL default '0',
`itemskill_id` INT(11) unsigned NOT NULL default '0',
`skill_lvl` TINYINT(4) unsigned NOT NULL default '0',
PRIMARY KEY (`char_id`,`hotkey`),
INDEX (`char_id`)
) TYPE=MYISAM;

View File

@ -46,6 +46,7 @@
char char_txt[1024] = "save/athena.txt";
char friends_txt[1024] = "save/friends.txt";
char hotkeys_txt[1024] = "save/hotkeys.txt";
char char_log_filename[1024] = "log/char.log";
int save_log = 1; // show loading/saving messages
@ -445,6 +446,22 @@ int mmo_friends_list_data_str(char *str, struct mmo_charstatus *p)
return 0;
}
/*---------------------------------------------------
Make a data line for hotkeys list
--------------------------------------------------*/
int mmo_hotkeys_tostr(char *str, struct mmo_charstatus *p)
{
int i;
char *str_p = str;
str_p += sprintf(str_p, "%d", p->char_id);
#ifdef HOTKEY_SAVING
for (i=0;i<HOTKEY_SAVING;i++)
str_p += sprintf(str_p, ",%d,%d,%d", p->hotkeys[i].type, p->hotkeys[i].id, p->hotkeys[i].lv);
#endif
str_p += '\0';
return 0;
}
//-------------------------------------------------
// Function to create the character line (for save)
//-------------------------------------------------
@ -891,6 +908,53 @@ int parse_friend_txt(struct mmo_charstatus *p)
return count;
}
//---------------------------------
// Function to read hotkey list
//---------------------------------
int parse_hotkey_txt(struct mmo_charstatus *p)
{
#ifdef HOTKEY_SAVING
char line[1024];
int pos = 0, count = 0, next;
int i,len;
int type, id, lv;
FILE *fp;
// Open the file and look for the ID
fp = fopen(hotkeys_txt, "r");
if(fp == NULL)
return -1;
while(fgets(line, sizeof(line), fp))
{
if(line[0] == '/' && line[1] == '/')
continue;
if (sscanf(line, "%d%n",&i, &pos) < 1 || i != p->char_id)
continue; //Not this line...
//Read hotkeys
len = strlen(line);
next = pos;
for (count = 0; next < len && count < HOTKEY_SAVING; count++)
{
if (sscanf(line+next, ",%d,%d,%d%n",&type,&id,&lv, &pos) < 3)
//Invalid entry?
break;
p->hotkeys[count].type = type;
p->hotkeys[count].id = id;
p->hotkeys[count].lv = lv;
next+=pos;
}
break; //Found hotkeys.
}
fclose(fp);
return count;
#else
return 0;
#endif
}
#ifndef TXT_SQL_CONVERT
//---------------------------------
// Function to read characters file
@ -944,7 +1008,9 @@ int mmo_char_init(void)
// Initialize friends list
parse_friend_txt(&char_dat[char_num].status); // Grab friends for the character
// Initialize hotkey list
parse_hotkey_txt(&char_dat[char_num].status); // Grab hotkeys for the character
if (ret > 0) { // negative value or zero for errors
if (char_dat[char_num].status.char_id >= char_id_count)
char_id_count = char_dat[char_num].status.char_id + 1;
@ -1049,7 +1115,17 @@ void mmo_char_sync(void)
lock_fclose(f_fp, friends_txt, &lock);
//aFree(id);
#ifdef HOTKEY_SAVING
// Hotkey List data save (Skotlex)
f_fp = lock_fopen(hotkeys_txt, &lock);
for(i = 0; i < char_num; i++) {
mmo_hotkeys_tostr(f_line, &char_dat[id[i]].status);
fprintf(f_fp, "%s" RETCODE, f_line);
}
lock_fclose(f_fp, hotkeys_txt, &lock);
#endif
DELETE_BUFFER(id);
return;
@ -4059,6 +4135,8 @@ int char_config_read(const char *cfgName)
strcpy(char_txt, w2);
} else if (strcmpi(w1, "friends_txt") == 0) { //By davidsiaw
strcpy(friends_txt, w2);
} else if (strcmpi(w1, "hotkeys_txt") == 0) { //By davidsiaw
strcpy(hotkeys_txt, w2);
#ifndef TXT_SQL_CONVERT
} else if (strcmpi(w1, "max_connect_user") == 0) {
max_connect_user = atoi(w2);

View File

@ -57,6 +57,7 @@ char guild_storage_db[256] = "guild_storage";
char party_db[256] = "party";
char pet_db[256] = "pet";
char friend_db[256] = "friends";
char hotkey_db[256] = "hotkey";
#ifndef TXT_SQL_CONVERT
static struct dbt *char_db_;
@ -731,7 +732,28 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){
strcat(save_status, " friends");
}
#ifdef HOTKEY_SAVING
// hotkeys
tmp_ptr = tmp_sql;
tmp_ptr += sprintf(tmp_ptr, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", hotkey_db);
diff = 0;
for(i = 0; i < ARRAYLENGTH(p->hotkeys); i++){
if(memcmp(&p->hotkeys[i], &cp->hotkeys[i], sizeof(struct hotkey)))
{
tmp_ptr += sprintf(tmp_ptr, "('%d','%d','%d','%d','%d'),", char_id, i, p->hotkeys[i].type, p->hotkeys[i].id , p->hotkeys[i].lv);
diff = 1;
}
}
if(diff) {
tmp_ptr[-1] = 0;
if(mysql_query(&mysql_handle, tmp_sql)){
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
} else {
strcat(save_status, " hotkeys");
}
}
#endif
if (save_status[0]!='\0' && save_log)
ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status);
#ifndef TXT_SQL_CONVERT
@ -1083,6 +1105,29 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
strcat (t_msg, " friends");
}
#ifdef HOTKEY_SAVING
//Hotkeys
sprintf(tmp_sql, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=%d ORDER BY `hotkey` LIMIT %d;", hotkey_db, char_id, HOTKEY_SAVING);
if(mysql_query(&mysql_handle, tmp_sql)){
ShowSQL("DB error - %s\n", mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__, __LINE__, tmp_sql);
}
sql_res = mysql_store_result(&mysql_handle);
if (sql_res) {
while ((sql_row = mysql_fetch_row(sql_res))) {
n = atoi(sql_row[0]);
if( n < 0 || n >= HOTKEY_SAVING)
continue;
p->hotkeys[n].type = atoi(sql_row[1]);
p->hotkeys[n].id = atoi(sql_row[2]);
p->hotkeys[n].lv = atoi(sql_row[3]);
}
mysql_free_result(sql_res);
strcat (t_msg, " hotkeys");
}
#endif
if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly!
cp = idb_ensure(char_db_, char_id, create_charstatus);
@ -3765,6 +3810,8 @@ void sql_config_read(const char* cfgName)
strcpy(pet_db,w2);
else if(!strcmpi(w1,"friend_db"))
strcpy(friend_db,w2);
else if(!strcmpi(w1,"hotkey_db"))
strcpy(hotkey_db,w2);
#ifndef TXT_SQL_CONVERT
else if(!strcmpi(w1,"db_path"))
strcpy(db_path,w2);

View File

@ -13,6 +13,11 @@
//Remove/Comment this line to disable sc_data saving. [Skotlex]
#define ENABLE_SC_SAVING
//Remove/Comment this line to disable server-side hot-key saving support [Skotlex]
//Note that newer clients no longer save hotkeys in the registry!
//The number is the max number of hotkeys to save (27 = 9 skills x 3 bars)
#define HOTKEY_SAVING 27
#define MAX_MAP_PER_SERVER 1024
#define MAX_INVENTORY 100
//Max number of characters per account. Note that changing this setting alone is not enough if the client is not hexed to support more characters as well.
@ -180,6 +185,14 @@ struct friend {
char name[NAME_LENGTH];
};
#ifdef HOTKEY_SAVING
struct hotkey {
unsigned int id;
unsigned short lv;
unsigned char type; // 0: item, 1: skill
};
#endif
struct mmo_charstatus {
int char_id;
int account_id;
@ -217,6 +230,9 @@ struct mmo_charstatus {
struct skill skill[MAX_SKILL];
struct friend friends[MAX_FRIENDS]; //New friend system [Skotlex]
#ifdef HOTKEY_SAVING
struct hotkey hotkeys[HOTKEY_SAVING];
#endif
};
struct registry {

View File

@ -10,6 +10,8 @@
//Note: The range is unlimited unless this define is set.
//#define AUTOLOOT_DISTANCE AREA_SIZE
#include "map.h"
enum AtCommandType {
AtCommand_None = -1,
AtCommand_Broadcast = 0,

View File

@ -8083,6 +8083,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
clif_updatestatus(sd,SP_NEXTJOBEXP);
clif_updatestatus(sd,SP_SKILLPOINT);
clif_initialstatus(sd);
clif_hotkeys_send(sd);
if (sd->sc.option&OPTION_FALCON)
clif_status_load(&sd->bl, SI_FALCON, 1);
@ -8193,6 +8194,38 @@ void clif_parse_TickSend(int fd, struct map_session_data *sd)
return;
}
void clif_hotkeys_send(struct map_session_data *sd) {
#ifdef HOTKEY_SAVING
const int fd = sd->fd;
int i;
if (!fd) return;
WFIFOHEAD(fd, 2+HOTKEY_SAVING*7);
WFIFOW(fd, 0) = 0x02b9;
for(i = 0; i < HOTKEY_SAVING; i++) {
WFIFOB(fd, 2 + 0 + i * 7) = sd->status.hotkeys[i].type; // type: 0: item, 1: skill
WFIFOL(fd, 2 + 1 + i * 7) = sd->status.hotkeys[i].id; // item or skill ID
WFIFOW(fd, 2 + 5 + i * 7) = sd->status.hotkeys[i].lv; // skill level
}
WFIFOSET(fd, packet_len(0x02b9));
#endif
}
void clif_parse_Hotkey(int fd, struct map_session_data *sd) {
#ifdef HOTKEY_SAVING
unsigned short idx;
int cmd;
cmd = RFIFOW(fd, 0);
idx = RFIFOW(fd, packet_db[sd->packet_ver][cmd].pos[0]);
if (idx >= HOTKEY_SAVING) return;
sd->status.hotkeys[idx].type = RFIFOB(fd, packet_db[sd->packet_ver][cmd].pos[1]);
sd->status.hotkeys[idx].id = RFIFOL(fd, packet_db[sd->packet_ver][cmd].pos[2]);
sd->status.hotkeys[idx].lv = RFIFOW(fd, packet_db[sd->packet_ver][cmd].pos[3]);
return;
#endif
}
/*==========================================
*
*------------------------------------------*/
@ -11705,7 +11738,7 @@ static int packetdb_readdb(void)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,191, 0, 0, 0, 0, 0, 0,
//#0x02C0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -11843,13 +11876,13 @@ static int packetdb_readdb(void)
{clif_parse_FeelSaveOk,"feelsaveok"},
{clif_parse_AdoptRequest,"adopt"},
{clif_parse_debug,"debug"},
//[blackhole89] //[orn]
{clif_parse_ChangeHomunculusName,"changehomunculusname"},
{clif_parse_HomMoveToMaster,"hommovetomaster"},
{clif_parse_HomMoveTo,"hommoveto"},
{clif_parse_HomAttack,"homattack"},
{clif_parse_HomMenu,"hommenu"},
{clif_parse_StoragePassword,"storagepassword"},
{clif_parse_Hotkey,"hotkey"},
{NULL,NULL}
};

View File

@ -144,6 +144,7 @@ void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const
int clif_soundeffectall(struct block_list* bl, const char *name, int type, enum send_target coverage);
void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, unsigned int tick);
void clif_parse_LoadEndAck(int fd,struct map_session_data *sd);
void clif_hotkeys_send(struct map_session_data *sd);
// trade
int clif_traderequest(struct map_session_data* sd, const char* name);

View File

@ -712,7 +712,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
// count the number of players eligible for exp sharing
for (i = c = 0; i < MAX_PARTY; i++) {
if( (sd[c] = p->data[i].sd) == NULL || sd[c]->bl.m != src->m || pc_isdead(sd[c]) ||
battle_config.idle_no_share && (sd[c]->chatID || sd[c]->vender_id || sd[c]->idletime < last_tick - battle_config.idle_no_share) )
(battle_config.idle_no_share && (sd[c]->chatID || sd[c]->vender_id || sd[c]->idletime < last_tick - battle_config.idle_no_share)) )
continue;
c++;
}