achievement.cpp 7.07 KB
#include "achievement.h"
#include "item.h"
#include "gateway.h"
#include "user.h"
#include "event.h"

achievement_cfg_mgr_t* g_achievement_cfg_mgr;

achievement_mgr_t::achievement_mgr_t()
{
	this->user = NULL;
}

void achievement_mgr_t::get_reward( uint32_t type_id, achievement_cfg_t* ac, gateway_msg::achievement_t* a )
{
	FOREACH(ac->item_map, it_item){
		user->item_mgr.add(it_item->first, it_item->second);
	}
	//更新内存		
	a->add_get_reward_id(ac->id);

	// 更新DB	
	std::string str_data;
	FOREACH_PB(a->get_reward_id, idx){
		str_data += el::convert_to_string(a->get_reward_id(idx));
		str_data += ",";
	}
	if (!str_data.empty()){
		str_data.pop_back();
	}
	
	user->event_mgr.update_event(user->uid(), common_msg::FOREVER_EVENT_ACHIEVEMENT+type_id, 0, a->data(), 0, str_data);

	//通知客户端,更新了.		
	{//notify
		gateway_msg::notify_achievement_msg_res out;
		gateway_msg::achievement_t* achievement = out.add_achievement();
		achievement->CopyFrom(*a);
		achievement->set_type_id(a->type_id() - common_msg::FOREVER_EVENT_ACHIEVEMENT);
		user->send_msg(cli_notify_achievement_msg_cmd, &out);
	}
}

void achievement_mgr_t::load_from_db( gateway_msg::achievement_t& achievement )
{
	this->achievement_map[achievement.type_id()] = achievement;
}

gateway_msg::achievement_t* achievement_mgr_t::find( uint32_t type_id )
{
	auto it = this->achievement_map.find(type_id);
	if (this->achievement_map.end() == it){
		return NULL;
	}
	return &it->second;
}

void achievement_mgr_t::update( uint32_t type_id, uint32_t data )
{
	uint32_t type = common_msg::FOREVER_EVENT_ACHIEVEMENT + type_id;

	gateway_msg::achievement_t* a = this->find(type);
	if (NULL == a){
		this->user->event_mgr.update_event(this->user->uid(), type, 0, data, 0);

		gateway_msg::achievement_t achievement;
		achievement.set_type_id(type);
		achievement.set_data(data);
		this->load_from_db(achievement);

		a = this->find(type);
	} else {
		a->set_data(data + a->data());

		std::string str_data;
		FOREACH_PB(a->get_reward_id, idx){
			str_data += el::convert_to_string(a->get_reward_id(idx));
			str_data += ",";
		}
		if (!str_data.empty()){
			str_data.pop_back();
		}
		this->user->event_mgr.update_event(this->user->uid(), type, 0, a->data(), 0, str_data);
	}

	{//notify
		gateway_msg::notify_achievement_msg_res out;
		gateway_msg::achievement_t* achievement = out.add_achievement();
		achievement->CopyFrom(*a);
		achievement->set_type_id(a->type_id() - common_msg::FOREVER_EVENT_ACHIEVEMENT);
		user->send_msg(cli_notify_achievement_msg_cmd, &out);
	}
}

uint32_t achievement_mgr_t::get_finish_cnt()
{
	uint32_t cnt = 0;
	FOREACH(this->achievement_map, it){
		gateway_msg::achievement_t& a = it->second;
		cnt += a.get_reward_id_size();
	}
	return cnt;
}


//////////////////////////////////////////////////////////////////////////
//achievement config
//////////////////////////////////////////////////////////////////////////

void achievement_cfg_mgr_t::init()
{
	this->achievement_map.clear();
	this->cnt_items_map.clear();
}

bool achievement_cfg_mgr_t::load_cfg()
{
	const std::string cfg_path = "./cfg/achievement.xml";
	el::lib_xmlparser_t xml;
	int ret = xml.open(cfg_path.c_str());
	if (SUCC != ret){
		ALERT_LOG("open");
		return false;
	}

	this->init();

	std::string str_def;
	xml.move2children_node();
	xmlNodePtr cur = xml.node_ptr;
	while (cur) {
		if (!xmlStrcmp(cur->name, (const xmlChar *)"type")) {
			uint32_t type_id = 0;
			xml.get_xml_prop(cur, type_id, "id");

			std::map<uint32_t, achievement_cfg_t> reward_map;
			xmlNodePtr child_cur = cur->xmlChildrenNode;
			while (child_cur) {
				if (!xmlStrcmp(child_cur->name, (const xmlChar *)"reward")) {
					achievement_cfg_t cfg;

					xml.get_xml_prop(child_cur, cfg.id, "id");
					xml.get_xml_prop(child_cur, cfg.data, "data");

					std::string str_item;
					xml.get_xml_prop_def(child_cur, str_item, "item", str_def);

					std::vector<uint_pair> uint_pair_val;
					str_split_uint(str_item, uint_pair_val);
					FOREACH(uint_pair_val, it) {
						if (NULL == g_item_cfg_mgr->find(it->key)){
							ALERT_LOG("[reward:%u]", it->key);
							return false;
						}
						if (!cfg.item_map.insert(std::make_pair(it->key, it->val)).second){
							ALERT_LOG("[reward item:%u]", it->key);
							return false;
						}
					}
					if (!reward_map.insert(std::make_pair(cfg.id, cfg)).second) {
						ALERT_LOG("[reward:%u]", cfg.id);
						return false;
					}
				}

				child_cur = child_cur->next;
			}//while
			if (!this->achievement_map.insert(std::make_pair(type_id, reward_map)).second) {
				ALERT_LOG("[type_id:%u]", type_id);
				return false;
			}
		} else if (!xmlStrcmp(cur->name, (const xmlChar *)"level")) {
			uint32_t cnt = 0;
			xml.get_xml_prop(cur, cnt, "cnt");

			std::string str_item;
			xml.get_xml_prop_def(cur, str_item, "item", str_def);
			std::map<ITEM_ID, ITEM_CNT> item_map;

			std::vector<uint_pair> uint_pair_val;
			str_split_uint(str_item, uint_pair_val);
			FOREACH(uint_pair_val, it) {
				if (NULL == g_item_cfg_mgr->find(it->key)){
					ALERT_LOG("[reward:%u]", it->key);
					return false;
				}
				if (!item_map.insert(std::make_pair(it->key, it->val)).second){
					ALERT_LOG("[reward item:%u]", it->key);
					return false;
				}
			}

			if (!this->cnt_items_map.insert(std::make_pair(cnt, item_map)).second) {
				ALERT_LOG("[cnt:%u]", cnt);
				return false;
			}
		}

		cur = cur->next;
	}//while

	return true;
}

achievement_cfg_t* achievement_cfg_mgr_t::find( uint32_t type_id, uint32_t reward_id )
{
	auto it = this->achievement_map.find(type_id);
	if (this->achievement_map.end() == it){
		return NULL;
	}
	auto it2 = it->second.find(reward_id);
	if (it->second.end() == it2){
		return NULL;
	}
	return &it2->second;
}

int gateway_t::on_get_achievement_reward_msg(el::lib_tcp_peer_info_t* peer_fd_info,
									  google::protobuf::Message* msg,
									  user_t* user)
{
	auto in = (gateway_msg::get_achievement_reward_msg*)msg;

	uint32_t type_id = in->type_id();
	uint32_t reward_id = in->reward_id();

	achievement_cfg_t* ac = g_achievement_cfg_mgr->find(type_id, reward_id);
	if (NULL == ac){
		WARN_LOG("");
		return share_msg::EC_VALUE_INVALID;
	}
	
	gateway_msg::achievement_t* a = user->achievement_mgr.find(common_msg::FOREVER_EVENT_ACHIEVEMENT + type_id);
	if (NULL == a){
		WARN_LOG("");
		return share_msg::EC_VALUE_INVALID;
	}
	
	if (a->data() < ac->data){
		WARN_LOG("");
		return share_msg::EC_VALUE_INVALID;
	}

	FOREACH_PB(a->get_reward_id, idx){
		uint32_t id = a->get_reward_id(idx);
		if (id == reward_id){
			WARN_LOG("");
			return share_msg::EC_VALUE_INVALID;
		}
	}

	{//return client
		gateway_msg::get_achievement_reward_msg_res out;
		user->send_msg_res(&out);
	}

	user->achievement_mgr.get_reward(type_id, ac, a);

	{
		uint32_t cnt = 0;
		FOREACH(user->achievement_mgr.achievement_map, it){
			gateway_msg::achievement_t& a = it->second;
			cnt += a.get_reward_id_size();
		}
		auto it_cnt_items = g_achievement_cfg_mgr->cnt_items_map.find(cnt);
		if (g_achievement_cfg_mgr->cnt_items_map.end() != it_cnt_items){
			std::map<ITEM_ID, ITEM_CNT>& item_map = it_cnt_items->second;
			FOREACH(item_map, it_item){
				user->item_mgr.add(it_item->first, it_item->second);
			}
		}
	}
	return 0;
}