예제 #1
0
파일: sqldbs.c 프로젝트: Lilystar/Auriga
/*==========================================
 * MYSQL_BINDにステートメント結果をセット
 *------------------------------------------
 */
bool sqldbs_stmt_bind_column(struct sqldbs_stmt *st, size_t idx, int buffer_type, void *buffer, size_t buffer_length)
{
	nullpo_retr(false, st);

	if(st->bind_columns == false) {
		size_t i, cols;

		// MYSQL_BINDの用意
		cols = sqldbs_stmt_field_count(st);
		if(st->max_columns < cols) {
			st->max_columns = cols;
			st->columns = (MYSQL_BIND *)aRealloc(st->columns, sizeof(MYSQL_BIND) * cols);
		}
		memset(st->columns, 0, cols * sizeof(MYSQL_BIND));
		for(i = 0; i < cols; i++) {
			st->columns[i].buffer_type = MYSQL_TYPE_NULL;
		}
	}

	if(idx >= st->max_columns)
		return false;

	sqldbs_stmt_bind_datatype(st->columns + idx, buffer_type, buffer, buffer_length, NULL, NULL);
	st->bind_columns = true;

	return true;
}
예제 #2
0
/**
 * Load achievements for a character.
 * @param char_id: Character ID
 * @param count: Pointer to return the number of found entries.
 * @return Array of found entries. It has *count entries, and it is care of the caller to aFree() it afterwards.
 */
struct achievement *mapif_achievements_fromsql(uint32 char_id, int *count)
{
	struct achievement *achievelog = NULL;
	struct achievement tmp_achieve;
	SqlStmt *stmt;
	StringBuf buf;
	int i;

	if (!count)
		return NULL;

	memset(&tmp_achieve, 0, sizeof(tmp_achieve));

	StringBuf_Init(&buf);
	StringBuf_AppendStr(&buf, "SELECT `id`, COALESCE(UNIX_TIMESTAMP(`completed`),0), COALESCE(UNIX_TIMESTAMP(`rewarded`),0)");
	for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; ++i)
		StringBuf_Printf(&buf, ", `count%d`", i + 1);
	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id` = '%u'", schema_config.achievement_table, char_id);

	stmt = SqlStmt_Malloc(sql_handle);
	if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
	||  SQL_ERROR == SqlStmt_Execute(stmt) )
	{
		SqlStmt_ShowDebug(stmt);
		SqlStmt_Free(stmt);
		StringBuf_Destroy(&buf);
		*count = 0;
		return NULL;
	}

	SqlStmt_BindColumn(stmt, 0, SQLDT_INT,  &tmp_achieve.achievement_id, 0, NULL, NULL);
	SqlStmt_BindColumn(stmt, 1, SQLDT_INT,  &tmp_achieve.completed, 0, NULL, NULL);
	SqlStmt_BindColumn(stmt, 2, SQLDT_INT,  &tmp_achieve.rewarded, 0, NULL, NULL);
	for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; ++i)
		SqlStmt_BindColumn(stmt, 3 + i, SQLDT_INT, &tmp_achieve.count[i], 0, NULL, NULL);

	*count = (int)SqlStmt_NumRows(stmt);
	if (*count > 0) {
		i = 0;

		achievelog = (struct achievement *)aCalloc(*count, sizeof(struct achievement));
		while (SQL_SUCCESS == SqlStmt_NextRow(stmt)) {
			if (i >= *count) // Sanity check, should never happen
				break;
			memcpy(&achievelog[i++], &tmp_achieve, sizeof(tmp_achieve));
		}
		if (i < *count) {
			// Should never happen. Compact array
			*count = i;
			achievelog = (struct achievement *)aRealloc(achievelog, sizeof(struct achievement) * i);
		}
	}

	SqlStmt_Free(stmt);
	StringBuf_Destroy(&buf);

	ShowInfo("achievement load complete from DB - id: %d (total: %d)\n", char_id, *count);

	return achievelog;
}
예제 #3
0
int acquire_timer (void)
{
	int i;

	if (free_timer_list_pos) {
		do {
			i = free_timer_list[--free_timer_list_pos];
		} while(i >= timer_data_num && free_timer_list_pos > 0);
	} else
		i = timer_data_num;

	if (i >= timer_data_num)
		for (i = timer_data_num; i < timer_data_max && timer_data[i].type; i++);
	if (i >= timer_data_num && i >= timer_data_max) {
		if (timer_data_max == 0) {
			timer_data_max = 256;
			timer_data = (struct TimerData*) aCalloc( sizeof(struct TimerData) , timer_data_max);
		} else {
			timer_data_max += 256;
			timer_data = (struct TimerData *) aRealloc( timer_data, sizeof(struct TimerData) * timer_data_max);
			memset(timer_data + (timer_data_max - 256), 0, sizeof(struct TimerData) * 256);
		}
	}

	return i;
}
예제 #4
0
/*======================================
 * 	CORE : Timer Heap
 *--------------------------------------
 */
static void push_timer_heap(int index)
{
	int i, j;
	int min, max, pivot; // for sorting

	// check number of element
	if (timer_heap_num >= timer_heap_max) {
		if (timer_heap_max == 0) {
			timer_heap_max = 256;
			timer_heap = (int *) aCalloc( sizeof(int) , 256);
		} else {
			timer_heap_max += 256;
			timer_heap = (int *) aRealloc( timer_heap, sizeof(int) * timer_heap_max);
			memset(timer_heap + (timer_heap_max - 256), 0, sizeof(int) * 256);
		}
	}

	// do a sorting from higher to lower
	j = timer_data[index].tick; // speed up
	// with less than 4 values, it's speeder to use simple loop
	if (timer_heap_num < 4) {
		for(i = timer_heap_num; i > 0; i--)
//			if (j < timer_data[timer_heap[i - 1]].tick) //Plain comparisons break on bound looping timers. [Skotlex]
			if (DIFF_TICK(j, timer_data[timer_heap[i - 1]].tick) < 0)
				break;
			else
				timer_heap[i] = timer_heap[i - 1];
		timer_heap[i] = index;
	// searching by dichotomie
	} else {
		// if lower actual item is higher than new
//		if (j < timer_data[timer_heap[timer_heap_num - 1]].tick) //Plain comparisons break on bound looping timers. [Skotlex]
		if (DIFF_TICK(j, timer_data[timer_heap[timer_heap_num - 1]].tick) < 0)
			timer_heap[timer_heap_num] = index;
		else {
			// searching position
			min = 0;
			max = timer_heap_num - 1;
			while (min < max) {
				pivot = (min + max) / 2;
//				if (j < timer_data[timer_heap[pivot]].tick) //Plain comparisons break on bound looping timers. [Skotlex]
				if (DIFF_TICK(j, timer_data[timer_heap[pivot]].tick) < 0)
					min = pivot + 1;
				else
					max = pivot;
			}
			// move elements - do loop if there are a little number of elements to move
			if (timer_heap_num - min < 5) {
				for(i = timer_heap_num; i > min; i--)
					timer_heap[i] = timer_heap[i - 1];
			// move elements - else use memmove (speeder for a lot of elements)
			} else
				memmove(&timer_heap[min + 1], &timer_heap[min], sizeof(int) * (timer_heap_num - min));
			// save new element
			timer_heap[min] = index;
		}
	}

	timer_heap_num++;
}
예제 #5
0
int do_timer(unsigned int tick)
{
	int i, nextmin = 1000;

	if (tick < 0x010000 && fix_heap_flag)
	{
		fix_timer_heap(tick);
		fix_heap_flag = 0;
	}

	while(timer_heap_num) {
		i = timer_heap[timer_heap_num - 1]; // next shorter element
		if ((nextmin = DIFF_TICK(timer_data[i].tick, tick)) > 0)
			break;
		if (timer_heap_num > 0) // suppress the actual element from the table
			timer_heap_num--;
		timer_data[i].type |= TIMER_REMOVE_HEAP;
		if (timer_data[i].func) {
			if (nextmin < -1000) {
				// 1秒以上の大幅な遅延が発生しているので、
				// timer処理タイミングを現在値とする事で
				// 呼び出し時タイミング(引数のtick)相対で処理してる
				// timer関数の次回処理タイミングを遅らせる
				timer_data[i].func(i, tick, timer_data[i].id, timer_data[i].data);
			} else {
				timer_data[i].func(i, timer_data[i].tick, timer_data[i].id, timer_data[i].data);
			}
		}
		if (timer_data[i].type & TIMER_REMOVE_HEAP) {
			switch(timer_data[i].type & ~TIMER_REMOVE_HEAP) {
			case TIMER_ONCE_AUTODEL:
				timer_data[i].type = 0;
				if (free_timer_list_pos >= free_timer_list_max) {
					free_timer_list_max += 256;
					free_timer_list = (int *) aRealloc(free_timer_list, sizeof(int) * free_timer_list_max);
					memset(free_timer_list + (free_timer_list_max - 256), 0, 256 * sizeof(int));
				}
				free_timer_list[free_timer_list_pos++] = i;
				break;
			case TIMER_INTERVAL:
				if (DIFF_TICK(timer_data[i].tick , tick) < -1000) {
					timer_data[i].tick = tick + timer_data[i].interval;
				} else {
					timer_data[i].tick += timer_data[i].interval;
				}
				timer_data[i].type &= ~TIMER_REMOVE_HEAP;
				push_timer_heap(i);
				break;
			}
		}
	}

	if (nextmin < TIMER_MIN_INTERVAL)
		nextmin = TIMER_MIN_INTERVAL;

	if ((unsigned int)(tick + nextmin) < tick) //Tick will loop, rearrange the heap on the next iteration.
		fix_heap_flag = 1;
	return nextmin;
}
예제 #6
0
/**
 * Loads the entire questlog for a character.
 *
 * @param char_id Character ID
 * @param count   Pointer to return the number of found entries.
 * @return Array of found entries. It has *count entries, and it is care of the
 *         caller to aFree() it afterwards.
 */
struct quest *mapif_quests_fromsql(int char_id, int *count) {
	struct quest *questlog = NULL;
	struct quest tmp_quest;
	SqlStmt *stmt;

	if (!count)
		return NULL;

	stmt = SQL->StmtMalloc(sql_handle);
	if (stmt == NULL) {
		SqlStmt_ShowDebug(stmt);
		*count = 0;
		return NULL;
	}

	memset(&tmp_quest, 0, sizeof(struct quest));

	if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `quest_id`, `state`, `time`, `count1`, `count2`, `count3` FROM `%s` WHERE `char_id`=?", quest_db)
	 || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
	 || SQL_ERROR == SQL->StmtExecute(stmt)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT,  &tmp_quest.quest_id, 0, NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT,  &tmp_quest.state,    0, NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UINT, &tmp_quest.time,     0, NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_INT,  &tmp_quest.count[0], 0, NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT,  &tmp_quest.count[1], 0, NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT,  &tmp_quest.count[2], 0, NULL, NULL)
	) {
		SqlStmt_ShowDebug(stmt);
		SQL->StmtFree(stmt);
		*count = 0;
		return NULL;
	}

	*count = (int)SQL->StmtNumRows(stmt);
	if (*count > 0) {
		int i = 0;
		questlog = (struct quest *)aCalloc(*count, sizeof(struct quest));

		while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
			if (i >= *count) // Sanity check, should never happen
				break;
			memcpy(&questlog[i++], &tmp_quest, sizeof(tmp_quest));
		}
		if (i < *count) {
			// Should never happen. Compact array
			*count = i;
			questlog = aRealloc(questlog, sizeof(struct quest)*i);
		}
	}

	SQL->StmtFree(stmt);
	return questlog;
}
예제 #7
0
void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count)
{
	unsigned int i;
	struct map_session_data* pl_sd;
	struct DBIterator *iter;
	struct s_search_store_search s;
	searchstore_searchall_t store_searchall;
	time_t querytime;
	DBMap *vending_db = vending_getdb();

	if( !battle_config.feature_search_stores ) {
		return;
	}

	if( !sd->searchstore.open ) {
		return;
	}

	if( ( store_searchall = searchstore_getsearchallfunc(type) ) == NULL ) {
		ShowError("searchstore_query: Unknown search type %u (account_id=%d).\n", (unsigned int)type, sd->bl.id);
		return;
	}

	time(&querytime);

	if( sd->searchstore.nextquerytime > querytime ) {
		clif_search_store_info_failed(sd, SSI_FAILED_LIMIT_SEARCH_TIME);
		return;
	}

	if( !sd->searchstore.uses ) {
		clif_search_store_info_failed(sd, SSI_FAILED_SEARCH_CNT);
		return;
	}

	// validate lists
	for( i = 0; i < item_count; i++ ) {
		if( !itemdb_exists(itemlist[i]) ) {
			ShowWarning("searchstore_query: Client resolved item %hu is not known.\n", itemlist[i]);
			clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
			return;
		}
	}
	for( i = 0; i < card_count; i++ ) {
		if( !itemdb_exists(cardlist[i]) ) {
			ShowWarning("searchstore_query: Client resolved card %hu is not known.\n", cardlist[i]);
			clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
			return;
		}
	}

	if( max_price < min_price ) {
		swap(min_price, max_price);
	}

	sd->searchstore.uses--;
	sd->searchstore.type = type;
	sd->searchstore.nextquerytime = querytime+battle_config.searchstore_querydelay;

	// drop previous results
	searchstore_clear(sd);

	// allocate max. amount of results
	sd->searchstore.items = (struct s_search_store_info_item*)aMalloc(sizeof(struct s_search_store_info_item)*battle_config.searchstore_maxresults);

	// search
	s.search_sd  = sd;
	s.itemlist   = itemlist;
	s.cardlist   = cardlist;
	s.item_count = item_count;
	s.card_count = card_count;
	s.min_price  = min_price;
	s.max_price  = max_price;
	iter         = db_iterator(vending_db);

	for( pl_sd = dbi_first(iter); dbi_exists(iter);  pl_sd = dbi_next(iter) ) {
		if( sd == pl_sd ) {// skip own shop, if any
			continue;
		}

		if( !store_searchall(pl_sd, &s) ) {// exceeded result size
			clif_search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT);
			break;
		}
	}

	dbi_destroy(iter);

	if( sd->searchstore.count ) {
		// reclaim unused memory
		sd->searchstore.items = (struct s_search_store_info_item*)aRealloc(sd->searchstore.items, sizeof(struct s_search_store_info_item)*sd->searchstore.count);

		// present results
		clif_search_store_info_ack(sd);

		// one page displayed
		sd->searchstore.pages++;
	} else {
		// cleanup
		searchstore_clear(sd);

		// update uses
		clif_search_store_info_ack(sd);

		// notify of failure
		clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
	}
}
예제 #8
0
/**
 * Loads the entire questlog for a character.
 *
 * @param char_id Character ID
 * @param count   Pointer to return the number of found entries.
 * @return Array of found entries. It has *count entries, and it is care of the
 *         caller to aFree() it afterwards.
 */
struct quest *mapif_quests_fromsql(int char_id, int *count) {
	struct quest *questlog = NULL;
	struct quest tmp_quest;
	SqlStmt *stmt;
	StringBuf buf;
	int i;
	int sqlerror = SQL_SUCCESS;

	if (!count)
		return NULL;

	stmt = SQL->StmtMalloc(sql_handle);
	if (stmt == NULL) {
		SqlStmt_ShowDebug(stmt);
		*count = 0;
		return NULL;
	}

	StrBuf->Init(&buf);
	StrBuf->AppendStr(&buf, "SELECT `quest_id`, `state`, `time`");
	for (i = 0; i < MAX_QUEST_OBJECTIVES; i++) {
		StrBuf->Printf(&buf, ", `count%d`", i+1);
	}
	StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`=?", quest_db);

	memset(&tmp_quest, 0, sizeof(struct quest));

	if (SQL_ERROR == SQL->StmtPrepare(stmt, StrBuf->Value(&buf))
	 || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
	 || SQL_ERROR == SQL->StmtExecute(stmt)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT,  &tmp_quest.quest_id, 0, NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT,  &tmp_quest.state,    0, NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UINT, &tmp_quest.time,     0, NULL, NULL)
	)
		sqlerror = SQL_ERROR;

	StrBuf->Destroy(&buf);

	for (i = 0; sqlerror != SQL_ERROR && i < MAX_QUEST_OBJECTIVES; i++) { // Stop on the first error
		sqlerror = SQL->StmtBindColumn(stmt, 3+i, SQLDT_INT,  &tmp_quest.count[i], 0, NULL, NULL);
	}

	if (sqlerror == SQL_ERROR) {
		SqlStmt_ShowDebug(stmt);
		SQL->StmtFree(stmt);
		*count = 0;
		return NULL;
	}

	*count = (int)SQL->StmtNumRows(stmt);
	if (*count > 0) {
		i = 0;
		questlog = (struct quest *)aCalloc(*count, sizeof(struct quest));

		while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
			if (i >= *count) // Sanity check, should never happen
				break;
			memcpy(&questlog[i++], &tmp_quest, sizeof(tmp_quest));
		}
		if (i < *count) {
			// Should never happen. Compact array
			*count = i;
			questlog = aRealloc(questlog, sizeof(struct quest)*i);
		}
	}

	SQL->StmtFree(stmt);
	return questlog;
}