Beispiel #1
0
/**
 * Adds an entry to a plugin data store.
 *
 * @param type[in]         The store type.
 * @param pluginID[in]     The plugin identifier.
 * @param storeptr[in,out] A pointer to the store. The store will be initialized if necessary.
 * @param data[in]         The data entry to add.
 * @param classid[in]      The entry class identifier.
 * @param autofree[in]     Whether the entry should be automatically freed when removed.
 */
void hplugins_addToHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store **storeptr, void *data, uint32 classid, bool autofree)
{
	struct hplugin_data_store *store;
	struct hplugin_data_entry *entry;
	int i;
	nullpo_retv(storeptr);

	if (!HPM->data_store_validate(type, storeptr, true)) {
		/* woo it failed! */
		ShowError("HPM:addToHPData:%s: failed, type %u (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
		return;
	}
	store = *storeptr;

	/* duplicate check */
	ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid);
	if (i != VECTOR_LENGTH(store->entries)) {
		ShowError("HPM:addToHPData:%s: error! attempting to insert duplicate struct of id %u and classid %u\n", HPM->pid2name(pluginID), pluginID, classid);
		return;
	}

	/* hplugin_data_entry is always same size, probably better to use the ERS (with reasonable chunk size e.g. 10/25/50) */
	CREATE(entry, struct hplugin_data_entry, 1);

	/* input */
	entry->pluginID = pluginID;
	entry->classid = classid;
	entry->flag.free = autofree ? 1 : 0;
	entry->data = data;

	VECTOR_ENSURE(store->entries, 1, 1);
	VECTOR_PUSH(store->entries, entry);
}
Beispiel #2
0
bool hplugins_addpacket(unsigned short cmd, unsigned short length, void (*receive) (int fd), unsigned int point, unsigned int pluginID)
{
	struct HPluginPacket *packet;
	int i;

	if (point >= hpPHP_MAX) {
		ShowError("HPM->addPacket:%s: unknown point '%u' specified for packet 0x%04x (len %d)\n",HPM->pid2name(pluginID),point,cmd,length);
		return false;
	}

	for (i = 0; i < VECTOR_LENGTH(HPM->packets[point]); i++) {
		if (VECTOR_INDEX(HPM->packets[point], i).cmd == cmd ) {
			ShowError("HPM->addPacket:%s: can't add packet 0x%04x, already in use by '%s'!",
					HPM->pid2name(pluginID), cmd, HPM->pid2name(VECTOR_INDEX(HPM->packets[point], i).pluginID));
			return false;
		}
	}

	VECTOR_ENSURE(HPM->packets[point], 1, 1);
	VECTOR_PUSHZEROED(HPM->packets[point]);
	packet = &VECTOR_LAST(HPM->packets[point]);

	packet->pluginID = pluginID;
	packet->cmd = cmd;
	packet->len = length;
	packet->receive = receive;

	return true;
}
Beispiel #3
0
/**
 * Exports a symbol to the shared symbols list.
 *
 * @param value The symbol value.
 * @param name  The symbol name.
 */
void hplugin_export_symbol(void *value, const char *name)
{
	struct hpm_symbol *symbol = NULL;
	CREATE(symbol ,struct hpm_symbol, 1);
	symbol->name = name;
	symbol->ptr = value;
	VECTOR_ENSURE(HPM->symbols, 1, 1);
	VECTOR_PUSH(HPM->symbols, symbol);
}
Beispiel #4
0
/**
 * Initializes the data structure for a new plugin and registers it.
 *
 * @return A (retained) pointer to the initialized data.
 */
struct hplugin *hplugin_create(void)
{
	struct hplugin *plugin = NULL;
	CREATE(plugin, struct hplugin, 1);
	plugin->idx = (int)VECTOR_LENGTH(HPM->plugins);
	plugin->filename = NULL;
	VECTOR_ENSURE(HPM->plugins, 1, 1);
	VECTOR_PUSH(HPM->plugins, plugin);
	return plugin;
}
Beispiel #5
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;
}
Beispiel #6
0
/**
 * 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;
}
Beispiel #7
0
/**
 * Creates a new console command entry.
 *
 * @param name The command name.
 * @param func The command callback.
 */
void console_parse_create(char *name, CParseFunc func)
{
	int i;
	char *tok;
	char sublist[CP_CMD_LENGTH * 5];
	struct CParseEntry *cmd;

	safestrncpy(sublist, name, CP_CMD_LENGTH * 5);
	tok = strtok(sublist,":");

	ARR_FIND(0, VECTOR_LENGTH(console->input->command_list), i, strcmpi(tok, VECTOR_INDEX(console->input->command_list, i)->cmd) == 0);

	if (i == VECTOR_LENGTH(console->input->command_list)) {
		CREATE(cmd, struct CParseEntry, 1);
		safestrncpy(cmd->cmd, tok, CP_CMD_LENGTH);
		cmd->type = CPET_UNKNOWN;
		VECTOR_ENSURE(console->input->commands, 1, 1);
		VECTOR_PUSH(console->input->commands, cmd);
		VECTOR_ENSURE(console->input->command_list, 1, 1);
		VECTOR_PUSH(console->input->command_list, cmd);
	}
Beispiel #8
0
/**
 * Adds a configuration listener for a plugin.
 *
 * @param pluginID The plugin identifier.
 * @param type     The configuration type to listen for.
 * @param name     The configuration entry name.
 * @param func     The callback function.
 * @retval true if the listener was added successfully.
 * @retval false in case of error.
 */
bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*parse_func) (const char *key, const char *val), int (*return_func) (const char *key))
{
	struct HPConfListenStorage *conf;
	int i;

	if (parse_func == NULL) {
		ShowError("HPM->addConf:%s: missing setter function for config '%s'\n",HPM->pid2name(pluginID),name);
		return false;
	}

	if (type == HPCT_BATTLE && return_func == NULL) {
		ShowError("HPM->addConf:%s: missing getter function for config '%s'\n",HPM->pid2name(pluginID),name);
		return false;
	}

	if (type >= HPCT_MAX) {
		ShowError("HPM->addConf:%s: unknown point '%u' specified for config '%s'\n",HPM->pid2name(pluginID),type,name);
		return false;
	}

	ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[type]), i, strcmpi(name, VECTOR_INDEX(HPM->config_listeners[type], i).key) == 0);
	if (i != VECTOR_LENGTH(HPM->config_listeners[type])) {
		ShowError("HPM->addConf:%s: duplicate '%s', already in use by '%s'!",
				HPM->pid2name(pluginID), name, HPM->pid2name(VECTOR_INDEX(HPM->config_listeners[type], i).pluginID));
		return false;
	}

	VECTOR_ENSURE(HPM->config_listeners[type], 1, 1);
	VECTOR_PUSHZEROED(HPM->config_listeners[type]);
	conf = &VECTOR_LAST(HPM->config_listeners[type]);

	conf->pluginID = pluginID;
	safestrncpy(conf->key, name, HPM_ADDCONF_LENGTH);
	conf->parse_func = parse_func;
	conf->return_func = return_func;

	return true;
}
Beispiel #9
0
// Loads new mails of this char_id/account_id
static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 mail_id, struct rodex_maillist *mails)
{
	int count = 0;
	struct rodex_message msg = { 0 };
	struct SqlStmt *stmt;

	nullpo_retr(-1, mails);

	stmt = SQL->StmtMalloc(inter->sql_handle);

	switch (opentype) {
	case RODEX_OPENTYPE_MAIL:
		if (SQL_ERROR == SQL->StmtPrepare(stmt,
			"SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`,"
			"`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`"
			"FROM `%s` WHERE `expire_date` > '%d' AND `receiver_id` = '%d' AND `mail_id` > '%"PRId64"'"
			"ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), char_id, mail_id)
			) {
			SqlStmt_ShowDebug(stmt);
			SQL->StmtFree(stmt);
			return -1;
		}
		break;

	case RODEX_OPENTYPE_ACCOUNT:
		if (SQL_ERROR == SQL->StmtPrepare(stmt,
			"SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`,"
			"`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`"
			"FROM `%s` WHERE "
			"`expire_date` > '%d' AND `receiver_accountid` = '%d' AND `mail_id` > '%"PRId64"'"
			"ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), account_id, mail_id)
			) {
			SqlStmt_ShowDebug(stmt);
			SQL->StmtFree(stmt);
			return -1;
		}
		break;

	case RODEX_OPENTYPE_RETURN:
		if (SQL_ERROR == SQL->StmtPrepare(stmt,
			"SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`,"
			"`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`"
			"FROM `%s` WHERE (`is_read` = 0 AND `sender_id` = '%d' AND `expire_date` <= '%d' AND `expire_date` + '%d' > '%d' AND `mail_id` > '%"PRId64"')"
			"ORDER BY `mail_id` ASC", rodex_db, char_id, (int)time(NULL), RODEX_EXPIRE, (int)time(NULL), mail_id)
			) {
			SqlStmt_ShowDebug(stmt);
			SQL->StmtFree(stmt);
			return -1;
		}
		break;

	case RODEX_OPENTYPE_UNSET:
		if (SQL_ERROR == SQL->StmtPrepare(stmt,
			"SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`,"
			"`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`"
			"FROM `%s` WHERE "
			"((`expire_date` > '%d' AND (`receiver_id` = '%d' OR `receiver_accountid` = '%d'))"
			"OR (`is_read` = 0 AND `sender_id` = '%d' AND `expire_date` <= '%d' AND `expire_date` + '%d' > '%d'))"
			"ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), char_id, account_id, char_id, (int)time(NULL), RODEX_EXPIRE, (int)time(NULL))
			) {
			SqlStmt_ShowDebug(stmt);
			SQL->StmtFree(stmt);
			return -1;
		}
		break;
	}

	if (SQL_ERROR == SQL->StmtExecute(stmt)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 0,  SQLDT_INT64,  &msg.id,                 sizeof msg.id,                 NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 1,  SQLDT_STRING, &msg.sender_name,        sizeof msg.sender_name,        NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 2,  SQLDT_INT,    &msg.sender_id,          sizeof msg.sender_id,          NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 3,  SQLDT_STRING, &msg.receiver_name,      sizeof msg.receiver_name,      NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 4,  SQLDT_INT,    &msg.receiver_id,        sizeof msg.receiver_id,        NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 5,  SQLDT_INT,    &msg.receiver_accountid, sizeof msg.receiver_accountid, NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 6,  SQLDT_STRING, &msg.title,              sizeof msg.title,              NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 7,  SQLDT_STRING, &msg.body,               sizeof msg.body,               NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 8,  SQLDT_INT64,  &msg.zeny,               sizeof msg.zeny,               NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 9,  SQLDT_UINT8,  &msg.type,               sizeof msg.type,               NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_BOOL,   &msg.is_read,            sizeof msg.is_read,            NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_BOOL,   &msg.sender_read,        sizeof msg.sender_read,        NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_INT,    &msg.send_date,          sizeof msg.send_date,          NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_INT,    &msg.expire_date,        sizeof msg.expire_date,        NULL, NULL)
	 || SQL_ERROR == SQL->StmtBindColumn(stmt, 14, SQLDT_INT,    &msg.weight,             sizeof msg.weight,             NULL, NULL)
	) {
		SqlStmt_ShowDebug(stmt);
		SQL->StmtFree(stmt);
		return -1;
	}

	{
		struct item it = { 0 };
		StringBuf buf;
		struct SqlStmt *stmt_items = SQL->StmtMalloc(inter->sql_handle);
		int i;

		if (stmt_items == NULL) {
			SQL->StmtFreeResult(stmt);
			SQL->StmtFree(stmt);
			return -1;
		}

		StrBuf->Init(&buf);

		StrBuf->AppendStr(&buf, "SELECT `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`");
		for (i = 0; i < MAX_SLOTS; i++) {
			StrBuf->Printf(&buf, ", `card%d`", i);
		}
		for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
			StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i);
		}
		StrBuf->Printf(&buf, "FROM `%s` WHERE mail_id = ? ORDER BY `mail_id` ASC", rodex_item_db);

		if (SQL_ERROR == SQL->StmtPrepareStr(stmt_items, StrBuf->Value(&buf))
		 || SQL_ERROR == SQL->StmtBindParam(stmt_items, 0, SQLDT_INT64, &msg.id, sizeof msg.id)
		) {
			SqlStmt_ShowDebug(stmt_items);
		}

		// Read mails
		while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {

			if (msg.type & MAIL_TYPE_ITEM) {
				if (SQL_ERROR == SQL->StmtExecute(stmt_items)
				 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 0,  SQLDT_INT,    &it.nameid,          sizeof it.nameid,      NULL, NULL)
				 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 1,  SQLDT_SHORT,  &it.amount,          sizeof it.amount,      NULL, NULL)
				 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 2,  SQLDT_UINT,   &it.equip,           sizeof it.equip,       NULL, NULL)
				 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 3,  SQLDT_CHAR,   &it.identify,        sizeof it.identify,    NULL, NULL)
				 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 4,  SQLDT_CHAR,   &it.refine,          sizeof it.refine,      NULL, NULL)
				 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 5,  SQLDT_CHAR,   &it.attribute,       sizeof it.attribute,   NULL, NULL)
				 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 6,  SQLDT_UINT,   &it.expire_time,     sizeof it.expire_time, NULL, NULL)
				 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 7,  SQLDT_UCHAR,  &it.bound,           sizeof it.bound,       NULL, NULL)
				 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 8,  SQLDT_UINT64, &it.unique_id,       sizeof it.unique_id,   NULL, NULL)
				) {
					SqlStmt_ShowDebug(stmt_items);
				}
				for (i = 0; i < MAX_SLOTS; i++) {
					if (SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9 + i, SQLDT_INT, &it.card[i], sizeof it.card[i], NULL, NULL))
						SqlStmt_ShowDebug(stmt_items);
				}
				for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
					if (SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9 + MAX_SLOTS + i * 2, SQLDT_INT16, &it.option[i].index, sizeof it.option[i].index, NULL, NULL)
					 || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 10 + MAX_SLOTS + i * 2, SQLDT_INT16, &it.option[i].value, sizeof it.option[i].value, NULL, NULL)
					) {
						SqlStmt_ShowDebug(stmt_items);
					}
				}

				for (i = 0; i < RODEX_MAX_ITEM && SQL_SUCCESS == SQL->StmtNextRow(stmt_items); ++i) {
					msg.items[i].item = it;
					msg.items_count++;
				}
			}

			if (msg.items_count == 0) {
				msg.type &= ~MAIL_TYPE_ITEM;
			}

			if (msg.zeny == 0) {
				msg.type &= ~MAIL_TYPE_ZENY;
			}

#if PACKETVER >= 20170419
			if (opentype == RODEX_OPENTYPE_UNSET) {
				if (msg.receiver_id == 0)
					msg.opentype = RODEX_OPENTYPE_ACCOUNT;
				else if (msg.expire_date < time(NULL))
					msg.opentype = RODEX_OPENTYPE_RETURN;
				else
					msg.opentype = RODEX_OPENTYPE_MAIL;
			} else {
				msg.opentype = opentype;
			}
#else
			msg.opentype = opentype;
#endif
#if PACKETVER < 20160601
			// NPC Message Type isn't supported in old clients
			msg.type &= ~MAIL_TYPE_NPC;
#endif

			++count;
			VECTOR_ENSURE(*mails, 1, 1);
			VECTOR_PUSH(*mails, msg);
			memset(&msg, 0, sizeof(struct rodex_message));

			SQL->StmtFreeResult(stmt_items);
		}
		StrBuf->Destroy(&buf);
		SQL->StmtFree(stmt_items);
	}

	SQL->StmtFreeResult(stmt);
	SQL->StmtFree(stmt);

	ShowInfo("rodex load complete from DB - id: %d (total: %d)\n", char_id, count);
	return count;
}
Beispiel #10
0
/**
 * Loads console commands list
 **/
void console_load_defaults(void)
{
	/**
	 * Defines a main category.
	 *
	 * Categories can't be used as commands!
	 * E.G.
	 * - sql update skip
	 *   'sql' is the main category
	 * CP_DEF_C(category)
	 **/
#define CP_DEF_C(x) { #x , CPET_CATEGORY, NULL , NULL, NULL }
	/**
	 * Defines a sub-category.
	 *
	 * Sub-categories can't be used as commands!
	 * E.G.
	 * - sql update skip
	 *   'update' is a sub-category
	 * CP_DEF_C2(command, category)
	 **/
#define CP_DEF_C2(x,y) { #x , CPET_CATEGORY, NULL , #y, NULL }
	/**
	 * Defines a command that is inside a category or sub-category
	 * CP_DEF_S(command, category/sub-category)
	 **/
#define CP_DEF_S(x,y) { #x, CPET_FUNCTION, CPCMD_C_A(x,y), #y, NULL }
	/**
	 * Defines a command that is _not_ inside any category
	 * CP_DEF_S(command)
	 **/
#define CP_DEF(x) { #x , CPET_FUNCTION, CPCMD_A(x), NULL, NULL }

	struct {
		char *name;
		int type;
		CParseFunc func;
		char *connect;
		struct CParseEntry *self;
	} default_list[] = {
		CP_DEF(help),
		/**
		 * Server related commands
		 **/
		CP_DEF_C(server),
		CP_DEF_S(ers_report,server),
		CP_DEF_S(mem_report,server),
		CP_DEF_S(malloc_usage,server),
		CP_DEF_S(exit,server),
		/**
		 * Sql related commands
		 **/
		CP_DEF_C(sql),
		CP_DEF_C2(update,sql),
		CP_DEF_S(skip,update),
	};
	int len = ARRAYLENGTH(default_list);
	struct CParseEntry *cmd;
	int i;

	VECTOR_ENSURE(console->input->commands, len, 1);

	for(i = 0; i < len; i++) {
		CREATE(cmd, struct CParseEntry, 1);

		safestrncpy(cmd->cmd, default_list[i].name, CP_CMD_LENGTH);

		cmd->type = default_list[i].type;

		switch (cmd->type) {
			case CPET_FUNCTION:
				cmd->u.func = default_list[i].func;
				break;
			case CPET_CATEGORY:
				VECTOR_INIT(cmd->u.children);
				break;
			case CPET_UNKNOWN:
				break;
		}

		VECTOR_PUSH(console->input->commands, cmd);
		default_list[i].self = cmd;
		if (!default_list[i].connect) {
			VECTOR_ENSURE(console->input->command_list, 1, 1);
			VECTOR_PUSH(console->input->command_list, cmd);
		}
	}

	for (i = 0; i < len; i++) {
		int k;
		if (!default_list[i].connect)
			continue;
		ARR_FIND(0, VECTOR_LENGTH(console->input->commands), k, strcmpi(default_list[i].connect, VECTOR_INDEX(console->input->commands, k)->cmd) == 0);
		if (k != VECTOR_LENGTH(console->input->commands)) {
			struct CParseEntry *parent = VECTOR_INDEX(console->input->commands, k);
			Assert_retb(parent->type == CPET_CATEGORY);
			cmd = default_list[i].self;
			VECTOR_ENSURE(parent->u.children, 1, 1);
			VECTOR_PUSH(parent->u.children, cmd);
		}
	}
#undef CP_DEF_C
#undef CP_DEF_C2
#undef CP_DEF_S
#undef CP_DEF
}