summaryrefslogtreecommitdiff
path: root/src/map/intif.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/intif.c')
-rw-r--r--src/map/intif.c259
1 files changed, 176 insertions, 83 deletions
diff --git a/src/map/intif.c b/src/map/intif.c
index b9d4d1746..0a36fbc3d 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -265,60 +265,117 @@ int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes)
return 0;
}
-int intif_regtostr(char* str, struct global_reg *reg, int qty)
-{
- int len =0, i;
-
- for (i = 0; i < qty; i++) {
- len+= sprintf(str+len, "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place.
- len+= sprintf(str+len, "%s", reg[i].value)+1;
- }
- return len;
-}
-
//Request for saving registry values.
-int intif_saveregistry(struct map_session_data *sd, int type)
-{
- struct global_reg *reg;
- int count;
- int i, p;
+int intif_saveregistry(struct map_session_data *sd) {
+ DBIterator *iter;
+ DBKey key;
+ DBData *data;
+ int plen = 0;
+ size_t len;
if (intif->CheckForCharServer())
return -1;
-
- switch (type) {
- case 3: //Character reg
- reg = sd->save_reg.global;
- count = sd->save_reg.global_num;
- sd->state.reg_dirty &= ~0x4;
- break;
- case 2: //Account reg
- reg = sd->save_reg.account;
- count = sd->save_reg.account_num;
- sd->state.reg_dirty &= ~0x2;
- break;
- case 1: //Account2 reg
- reg = sd->save_reg.account2;
- count = sd->save_reg.account2_num;
- sd->state.reg_dirty &= ~0x1;
- break;
- default: //Broken code?
- ShowError("intif_saveregistry: Invalid type %d\n", type);
- return -1;
- }
- WFIFOHEAD(inter_fd, 288 * MAX_REG_NUM+13);
- WFIFOW(inter_fd,0)=0x3004;
- WFIFOL(inter_fd,4)=sd->status.account_id;
- WFIFOL(inter_fd,8)=sd->status.char_id;
- WFIFOB(inter_fd,12)=type;
- for( p = 13, i = 0; i < count; i++ ) {
- if (reg[i].str[0] != '\0' && reg[i].value[0] != '\0') {
- p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place.
- p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].value)+1;
+
+ WFIFOHEAD(inter_fd, 60000 + 300);
+ WFIFOW(inter_fd,0) = 0x3004;
+ /* 0x2 = length (set later) */
+ WFIFOL(inter_fd,4) = sd->status.account_id;
+ WFIFOL(inter_fd,8) = sd->status.char_id;
+ WFIFOW(inter_fd,12) = 0;/* count */
+
+ plen = 14;
+
+ iter = db_iterator(sd->var_db);
+ for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) {
+ const char *varname = NULL;
+ void *src = NULL;
+
+ if( data->type != DB_DATA_PTR ) /* its a @number */
+ continue;
+
+ varname = script->get_str(script_getvarid(key.i64));
+
+ if( varname[0] == '@' ) /* @string$ can get here, so we skip */
+ continue;
+
+ src = DB->data2ptr(data);
+
+ /* no need! */
+ if( !((struct script_reg_state*)src)->update )
+ continue;
+
+ ((struct script_reg_state*)src)->update = false;
+
+ len = strlen(varname)+1;
+
+ WFIFOB(inter_fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */
+ plen += 1;
+
+ safestrncpy((char*)WFIFOP(inter_fd,plen), varname, len);
+ plen += len;
+
+ WFIFOL(inter_fd, plen) = script_getvaridx(key.i64);
+ plen += 4;
+
+ if( ((struct script_reg_state*)src)->type ) {
+ struct script_reg_str *p = src;
+
+ WFIFOB(inter_fd, plen) = p->value ? 2 : 3;
+ plen += 1;
+
+ if( p->value ) {
+ len = strlen(p->value)+1;
+
+ WFIFOB(inter_fd, plen) = (unsigned char)len;/* won't be higher; the column size is 254 */
+ plen += 1;
+
+ safestrncpy((char*)WFIFOP(inter_fd,plen), p->value, len);
+ plen += len;
+ } else {
+ script->reg_destroy_single(sd,key.i64,&p->flag);
+ }
+
+ } else {
+ struct script_reg_num *p = src;
+
+ WFIFOB(inter_fd, plen) = p->value ? 0 : 1;
+ plen += 1;
+
+ if( p->value ) {
+ WFIFOL(inter_fd, plen) = p->value;
+ plen += 4;
+ } else {
+ script->reg_destroy_single(sd,key.i64,&p->flag);
+ }
+
+ }
+
+ WFIFOW(inter_fd,12) += 1;
+
+ if( plen > 60000 ) {
+ WFIFOW(inter_fd, 2) = plen;
+ WFIFOSET(inter_fd, plen);
+
+ /* prepare follow up */
+ WFIFOHEAD(inter_fd, 60000 + 300);
+ WFIFOW(inter_fd,0) = 0x3004;
+ /* 0x2 = length (set later) */
+ WFIFOL(inter_fd,4) = sd->status.account_id;
+ WFIFOL(inter_fd,8) = sd->status.char_id;
+ WFIFOW(inter_fd,12) = 0;/* count */
+
+ plen = 14;
}
+
}
- WFIFOW(inter_fd,2)=p;
- WFIFOSET(inter_fd,WFIFOW(inter_fd,2));
+ dbi_destroy(iter);
+
+ /* mark & go. */
+ WFIFOW(inter_fd, 2) = plen;
+ WFIFOSET(inter_fd, plen);
+
+ sd->vars_dirty = false;
+
return 0;
}
@@ -327,10 +384,7 @@ int intif_request_registry(struct map_session_data *sd, int flag)
{
nullpo_ret(sd);
- sd->save_reg.account2_num = -1;
- sd->save_reg.account_num = -1;
- sd->save_reg.global_num = -1;
-
+ /* if char server aint online it doesn't load, shouldn't we kill the session then? */
if (intif->CheckForCharServer())
return 0;
@@ -927,54 +981,93 @@ void mapif_parse_WisToGM(int fd)
// Request player registre
void intif_parse_Registers(int fd)
{
- int j,p,len,max, flag;
+ int i, flag;
struct map_session_data *sd;
- struct global_reg *reg;
- int *qty;
int account_id = RFIFOL(fd,4), char_id = RFIFOL(fd,8);
struct auth_node *node = chrif->auth_check(account_id, char_id, ST_LOGIN);
+ char type = RFIFOB(fd, 13);
+
if (node)
sd = node->sd;
else { //Normally registries should arrive for in log-in chars.
sd = map->id2sd(account_id);
- if (sd && RFIFOB(fd,12) == 3 && sd->status.char_id != char_id)
- sd = NULL; //Character registry from another character.
}
- if (!sd) return;
-
- flag = (sd->save_reg.global_num == -1 || sd->save_reg.account_num == -1 || sd->save_reg.account2_num == -1);
-
+
+ if (!sd || sd->status.char_id != char_id) {
+ return; //Character registry from another character.
+ }
+
+ flag = ( sd->vars_received&PRL_ACCG && sd->vars_received&PRL_ACCL && sd->vars_received&PRL_CHAR ) ? 0 : 1;
+
switch (RFIFOB(fd,12)) {
case 3: //Character Registry
- reg = sd->save_reg.global;
- qty = &sd->save_reg.global_num;
- max = GLOBAL_REG_NUM;
- break;
+ sd->vars_received |= PRL_CHAR;
+ break;
case 2: //Account Registry
- reg = sd->save_reg.account;
- qty = &sd->save_reg.account_num;
- max = ACCOUNT_REG_NUM;
- break;
+ sd->vars_received |= PRL_ACCL;
+ break;
case 1: //Account2 Registry
- reg = sd->save_reg.account2;
- qty = &sd->save_reg.account2_num;
- max = ACCOUNT_REG2_NUM;
- break;
+ sd->vars_received |= PRL_ACCG;
+ break;
+ case 0:
+ break;
default:
ShowError("intif_parse_Registers: Unrecognized type %d\n",RFIFOB(fd,12));
return;
}
- for(j=0,p=13;j<max && p<RFIFOW(fd,2);j++){
- sscanf((char*)RFIFOP(fd,p), "%31c%n", reg[j].str,&len);
- reg[j].str[len]='\0';
- p += len+1; //+1 to skip the '\0' between strings.
- sscanf((char*)RFIFOP(fd,p), "%255c%n", reg[j].value,&len);
- reg[j].value[len]='\0';
- p += len+1;
+ /* have it not complain about insertion of vars before loading, and not set those vars as new or modified */
+ pc->reg_load = true;
+
+ if( RFIFOW(fd, 14) ) {
+ char key[32], sval[254];
+ unsigned int index;
+ int max = RFIFOW(fd, 14), cursor = 16, ival;
+
+ /**
+ * Vessel!char_reg_num_db
+ *
+ * str type
+ * { keyLength(B), key(<keyLength>), index(L), valLength(B), val(<valLength>) }
+ **/
+ if( type ) {
+ for(i = 0; i < max; i++) {
+ safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor));
+ cursor += RFIFOB(fd, cursor) + 1;
+
+ index = RFIFOL(fd, cursor);
+ cursor += 4;
+
+ safestrncpy(sval, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor));
+ cursor += RFIFOB(fd, cursor) + 1;
+
+ script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)sval, NULL);
+ }
+ /**
+ * Vessel!
+ *
+ * int type
+ * { keyLength(B), key(<keyLength>), index(L), value(L) }
+ **/
+ } else {
+ for(i = 0; i < max; i++) {
+ safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor));
+ cursor += RFIFOB(fd, cursor) + 1;
+
+ index = RFIFOL(fd, cursor);
+ cursor += 4;
+
+ ival = RFIFOL(fd, cursor);
+ cursor += 4;
+
+ script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)__64BPTRSIZE(ival), NULL);
+ }
+ }
}
- *qty = j;
-
- if (flag && sd->save_reg.global_num > -1 && sd->save_reg.account_num > -1 && sd->save_reg.account2_num > -1)
+
+ /* flag it back */
+ pc->reg_load = false;
+
+ if (flag && sd->vars_received&PRL_ACCG && sd->vars_received&PRL_ACCL && sd->vars_received&PRL_CHAR)
pc->reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex]
}