/** * Cleaning function called through db_destroy() */ static int inter_achievement_char_achievements_clear(union DBKey key, struct DBData *data, va_list args) { struct char_achievements *ca = DB->data2ptr(data); VECTOR_CLEAR(*ca); return 0; }
/** * Saves changed achievements for a character. * @param[in] char_id character identifier. * @param[out] cp pointer to loaded achievements. * @param[in] p pointer to map-sent character achievements. * @return number of achievements saved. */ static int inter_achievement_tosql(int char_id, struct char_achievements *cp, const struct char_achievements *p) { StringBuf buf; int i = 0, rows = 0; nullpo_ret(cp); nullpo_ret(p); Assert_ret(char_id > 0); StrBuf->Init(&buf); StrBuf->Printf(&buf, "REPLACE INTO `%s` (`char_id`, `ach_id`, `completed_at`, `rewarded_at`", char_achievement_db); for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; i++) StrBuf->Printf(&buf, ", `obj_%d`", i); StrBuf->AppendStr(&buf, ") VALUES "); for (i = 0; i < VECTOR_LENGTH(*p); i++) { int j = 0; bool save = false; struct achievement *pa = &VECTOR_INDEX(*p, i), *cpa = NULL; ARR_FIND(0, VECTOR_LENGTH(*cp), j, ((cpa = &VECTOR_INDEX(*cp, j)) && cpa->id == pa->id)); if (j == VECTOR_LENGTH(*cp)) save = true; else if (memcmp(cpa, pa, sizeof(struct achievement)) != 0) save = true; if (save) { StrBuf->Printf(&buf, "%s('%d', '%d', '%"PRId64"', '%"PRId64"'", rows ?", ":"", char_id, pa->id, (int64)pa->completed_at, (int64)pa->rewarded_at); for (j = 0; j < MAX_ACHIEVEMENT_OBJECTIVES; j++) StrBuf->Printf(&buf, ", '%d'", pa->objective[j]); StrBuf->AppendStr(&buf, ")"); rows++; } } if (rows > 0 && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) { Sql_ShowDebug(inter->sql_handle); StrBuf->Destroy(&buf); // Destroy the buffer. return 0; } // Destroy the buffer. StrBuf->Destroy(&buf); if (rows) { ShowInfo("achievements saved for char %d (total: %d, saved: %d)\n", char_id, VECTOR_LENGTH(*p), rows); /* Sync with inter-db acheivements. */ VECTOR_CLEAR(*cp); VECTOR_ENSURE(*cp, VECTOR_LENGTH(*p), 1); VECTOR_PUSHARRAY(*cp, VECTOR_DATA(*p), VECTOR_LENGTH(*p)); } return rows; }
/** * Retrieves all achievements of a character. * @param[in] char_id character identifier. * @param[out] cp pointer to character achievements structure. * @return true on success, false on failure. */ static bool inter_achievement_fromsql(int char_id, struct char_achievements *cp) { StringBuf buf; char *data; int i = 0, num_rows = 0; nullpo_ret(cp); Assert_ret(char_id > 0); // char_achievements (`char_id`, `ach_id`, `completed_at`, `rewarded_at`, `obj_0`, `obj_2`, ...`obj_9`) StrBuf->Init(&buf); StrBuf->AppendStr(&buf, "SELECT `ach_id`, `completed_at`, `rewarded_at`"); for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; i++) StrBuf->Printf(&buf, ", `obj_%d`", i); StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id` = '%d' ORDER BY `ach_id`", char_achievement_db, char_id); if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) { Sql_ShowDebug(inter->sql_handle); StrBuf->Destroy(&buf); return false; } VECTOR_CLEAR(*cp); if ((num_rows = (int) SQL->NumRows(inter->sql_handle)) != 0) { int j = 0; VECTOR_ENSURE(*cp, num_rows, 1); for (i = 0; i < num_rows && SQL_SUCCESS == SQL->NextRow(inter->sql_handle); i++) { struct achievement t_ach = { 0 }; SQL->GetData(inter->sql_handle, 0, &data, NULL); t_ach.id = atoi(data); SQL->GetData(inter->sql_handle, 1, &data, NULL); t_ach.completed_at = atoi(data); SQL->GetData(inter->sql_handle, 2, &data, NULL); t_ach.rewarded_at = atoi(data); /* Objectives */ for (j = 0; j < MAX_ACHIEVEMENT_OBJECTIVES; j++) { SQL->GetData(inter->sql_handle, j + 3, &data, NULL); t_ach.objective[j] = atoi(data); } /* Add Entry */ VECTOR_PUSH(*cp, t_ach); } } SQL->FreeResult(inter->sql_handle); StrBuf->Destroy(&buf); if (num_rows > 0) ShowInfo("achievements loaded for char %d (total: %d)\n", char_id, num_rows); return true; }
void mapif_parse_rodex_requestinbox(int fd) { int count; int char_id = RFIFOL(fd,2); int account_id = RFIFOL(fd, 6); int8 flag = RFIFOB(fd, 10); int8 opentype = RFIFOB(fd, 11); int64 mail_id = RFIFOQ(fd, 12); struct rodex_maillist mails = { 0 }; VECTOR_INIT(mails); if (flag == 0) count = inter_rodex->fromsql(char_id, account_id, opentype, 0, &mails); else count = inter_rodex->fromsql(char_id, account_id, opentype, mail_id, &mails); mapif->rodex_sendinbox(fd, char_id, opentype, flag, count, mail_id, &mails); VECTOR_CLEAR(mails); }