#include "precompile.h" #include #include #include "guild.h" #include "dbengine.h" #include "app.h" #include "guildmgr.h" #include "typeconvert.h" #include "utils.h" #include "dbhelper.h" #include "synchelper.h" const int GUILD_MAX_MEMBER_NUM = 50; enum GuildApplyStatus_e { kGuildApplyPending = 0, kGuildApplyAgree = 1, kGuildApplyReject = 2, kGuildApplyIgnore = 3, }; void Guild::Init() { logdb_ = new ss::MFGuildLogDB; } void Guild::UnInit() { for (auto& pair : member_hash_) { delete pair.second; } member_hash_.clear(); for (auto& pair : apply_hash_) { delete pair.second; } apply_hash_.clear(); A8_SAFE_DELETE(logdb_); } GuildMember* Guild::GetMember(const std::string& account_id) { auto itr = member_hash_.find(account_id); return itr != member_hash_.end() ? itr->second : nullptr; } bool Guild::IsFull() { return member_hash_.size() >= GUILD_MAX_MEMBER_NUM; } void Guild::AddMember(GuildMember* member) { if (member_hash_.find(member->account_id) != member_hash_.end()) { abort(); } member_hash_[member->account_id] = member; GenSortedMembers(); MarkDirty(); if (dirty_timer_) { a8::Timer::Instance()->ModifyTimer(dirty_timer_, 100); } } void Guild::RemoveMember(const std::string& sender_id, const std::string& target_id, int reason) { GuildMember* member = GetMember(target_id); if (member) { SyncHelper::Instance()->SyncGuildMemberQuit ( this, sender_id, target_id, reason ); member_hash_.erase(target_id); A8_SAFE_DELETE(member); GenSortedMembers(); } MarkDirty(); if (dirty_timer_) { a8::Timer::Instance()->ModifyTimer(dirty_timer_, 100); } } void Guild::MarkDirty() { if (!dirty_) { dirty_ = true; dirty_timer_ = a8::Timer::Instance()->AddDeadLineTimerAndAttach (1000 * 60, a8::XParams() .SetSender((void*)this), [] (const a8::XParams& param) { Guild* guild = (Guild*)param.sender.GetUserData(); guild->SaveToDB(); }, &timer_attacher_.timer_list_, [] (const a8::XParams& param) { Guild* guild = (Guild*)param.sender.GetUserData(); guild->dirty_timer_ = nullptr; } ); } } void Guild::Deserialize(const std::string& guild_data, const std::string& guild_log) { logdb_->ParseFromString(guild_log); ss::MFGuildDB guilddb; guilddb.ParseFromString(guild_data); for (auto& member_pb : guilddb.members()) { GuildMember* member = new GuildMember; TypeConvert::Convert(member_pb.base_data(), *member); member_hash_[member->account_id] = member; } GenSortedMembers(); } void Guild::_CMGuildInfo(f8::MsgHdr& hdr, const cs::CMGuildInfo& msg) { ss::SS_IM_ForwardGuildCMMsg *forward_msg = (ss::SS_IM_ForwardGuildCMMsg*)hdr.user_data; cs::SMGuildInfo respmsg; FillGuildBasic(respmsg.mutable_info()); GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); } void Guild::_CMGuildJoin(f8::MsgHdr& hdr, const cs::CMGuildJoin& msg) { ss::SS_IM_ForwardGuildCMMsg *forward_msg = (ss::SS_IM_ForwardGuildCMMsg*)hdr.user_data; cs::SMGuildJoin respmsg; GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); GuildMember* member = GetMember(forward_msg->context().user_info().base_data().account_id()); if (member) { SyncHelper::Instance()->SyncGuildMemberUpdate(this, member, kGuildUpdateReasonJoin); } else { DBHelper::Instance()->AddGuildApply(this, forward_msg->context().user_info()); } } void Guild::_CMGuildAgree(f8::MsgHdr& hdr, const cs::CMGuildAgree& msg) { ss::SS_IM_ForwardGuildCMMsg *forward_msg = (ss::SS_IM_ForwardGuildCMMsg*)hdr.user_data; cs::SMGuildAgree respmsg; GuildMember* member = GetMember(forward_msg->context().user_info().base_data().account_id()); if (member) { SyncHelper::Instance()->SyncGuildMemberUpdate(this, member, kGuildUpdateReasonAgree); GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); DBHelper::Instance()->SetGuildApplyStatus ( msg.apply().base_data().account_id(), guild_id_, kGuildApplyAgree ); ClearApplyBySenderId(msg.apply().base_data().account_id()); return; } if (IsFull()) { SendErrorMsg(hdr.socket_handle, forward_msg->context(), "公会人数已达上限"); respmsg.set_errcode(1); respmsg.set_errmsg("公会人数已达上限"); GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); return; } GuildMember* sender = GetMember(forward_msg->context().user_info().base_data().account_id()); if (!sender) { SendErrorMsg(hdr.socket_handle, forward_msg->context(), "服务器内部错误"); respmsg.set_errcode(2); respmsg.set_errmsg("服务器内部错误"); GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); return; } if (!(sender->guild_job == kGuildOwner || sender->guild_job == kGuildAdmin)) { SendErrorMsg(hdr.socket_handle, forward_msg->context(), "权限不够"); respmsg.set_errcode(3); respmsg.set_errmsg("权限不够"); GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); return; } GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); member = new GuildMember(); TypeConvert::Convert(forward_msg->context().user_info().base_data(), *member); AddMember(member); SyncHelper::Instance()->SyncGuildMemberUpdate(this, member, kGuildUpdateReasonAgree); DBHelper::Instance()->SetGuildApplyStatus ( msg.apply().base_data().account_id(), guild_id_, kGuildApplyAgree ); ClearApplyBySenderId(msg.apply().base_data().account_id()); } void Guild::_CMGuildKick(f8::MsgHdr& hdr, const cs::CMGuildKick& msg) { ss::SS_IM_ForwardGuildCMMsg *forward_msg = (ss::SS_IM_ForwardGuildCMMsg*)hdr.user_data; cs::SMGuildKick respmsg; GuildMember* sender = GetMember(forward_msg->context().user_info().base_data().account_id()); if (!sender) { SendErrorMsg(hdr.socket_handle, forward_msg->context(), "服务器内部错误"); respmsg.set_errcode(2); respmsg.set_errmsg("服务器内部错误"); GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); return; } if (!(sender->guild_job == kGuildOwner || sender->guild_job == kGuildAdmin)) { SendErrorMsg(hdr.socket_handle, forward_msg->context(), "权限不够"); respmsg.set_errcode(3); respmsg.set_errmsg("权限不够"); GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); return; } GuildMember* member = GetMember(msg.account_id()); if (!member) { GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); return; } GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); RemoveMember(sender->account_id, member->account_id, kGuildKick); } void Guild::_CMGuildQuit(f8::MsgHdr& hdr, const cs::CMGuildQuit& msg) { ss::SS_IM_ForwardGuildCMMsg *forward_msg = (ss::SS_IM_ForwardGuildCMMsg*)hdr.user_data; cs::SMGuildQuit respmsg; GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); GuildMember* sender = GetMember(forward_msg->context().user_info().base_data().account_id()); if (sender) { if (sender->guild_job != kGuildOwner) { RemoveMember(sender->account_id, sender->account_id, kGuildQuit); } } } void Guild::_CMGuildDismiss(f8::MsgHdr& hdr, const cs::CMGuildDismiss& msg) { ss::SS_IM_ForwardGuildCMMsg *forward_msg = (ss::SS_IM_ForwardGuildCMMsg*)hdr.user_data; cs::SMGuildDismiss respmsg; GuildMember* sender = GetMember(forward_msg->context().user_info().base_data().account_id()); if (sender) { if (sender->guild_job != kGuildOwner) { SendErrorMsg(hdr.socket_handle, forward_msg->context(), "权限不够"); respmsg.set_errcode(3); respmsg.set_errmsg("权限不够"); GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); return; } } GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); for (auto& pair : member_hash_) { RemoveMember(sender->account_id, pair.second->account_id, kGuildDismisss); } guild_status_ = kGuildDismissed; SaveToDB(); } void Guild::_CMGuildRename(f8::MsgHdr& hdr, const cs::CMGuildRename& msg) { ss::SS_IM_ForwardGuildCMMsg *forward_msg = (ss::SS_IM_ForwardGuildCMMsg*)hdr.user_data; guild_name_ = msg.new_name(); cs::SMGuildRename respmsg; GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); MarkDirty(); } void Guild::_CMGuildMemberList(f8::MsgHdr& hdr, const cs::CMGuildMemberList& msg) { ss::SS_IM_ForwardGuildCMMsg *forward_msg = (ss::SS_IM_ForwardGuildCMMsg*)hdr.user_data; cs::SMGuildMemberList respmsg; *respmsg.mutable_paging() = msg.paging(); if (respmsg.paging().page_size() <= 0) { respmsg.mutable_paging()->set_page_size(10); } AdjustPaging(respmsg.mutable_paging(), sorted_members_.size()); for (size_t i = respmsg.paging().curr_page() * respmsg.paging().page_size(); i < sorted_members_.size(); ++i) { if (respmsg.member_list().size() >= respmsg.paging().page_size()) { break; } auto p = respmsg.add_member_list(); TypeConvert::Convert(*sorted_members_[i], *p); } GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle, forward_msg->context(), respmsg); } void Guild::_CMGuildApplyList(f8::MsgHdr& hdr, const cs::CMGuildApplyList& msg) { auto on_ok = [] (a8::XParams& param, const f8::DataSet* data_set) { cs::MFPaging* paging = (cs::MFPaging*)param.param2.GetUserData(); ss::SS_IM_ForwardGuildCMMsg* forward_msg = (ss::SS_IM_ForwardGuildCMMsg*) param.param3.GetUserData(); Guild* guild = GuildMgr::Instance()->GetGuild(param.sender); if (guild) { for (auto& row : *data_set) { GuildApply* apply = new GuildApply; apply->idx = a8::XValue(row[0]); apply->applyid = a8::XValue(row[1]); apply->guild_id = a8::XValue(row[2]); apply->base_data.account_id = row[3]; apply->base_data.nickname = row[4]; apply->base_data.avatar_url = row[5]; apply->base_data.sex = a8::XValue(row[6]); apply->base_data.base_data_version = a8::XValue(row[7]); apply->base_data.user_value1 = a8::XValue(row[8]); apply->base_data.user_value2 = a8::XValue(row[9]); apply->base_data.user_value3 = a8::XValue(row[10]); guild->apply_hash_[apply->idx] = apply; if (apply->idx > guild->last_apply_idx_) { guild->last_apply_idx_ = apply->idx; } } cs::SMGuildApplyList respmsg; guild->FillApplyList(forward_msg->context().user_info().base_data().account_id(), *paging, respmsg); GuildMgr::Instance()->ForwardGuildSMMsg(param.param1, forward_msg->context(), respmsg); } delete forward_msg; delete paging; }; auto on_error = [] (a8::XParams& param, int error_code, const std::string& error_msg) { cs::MFPaging* paging = (cs::MFPaging*)param.param2.GetUserData(); ss::SS_IM_ForwardGuildCMMsg* forward_msg = (ss::SS_IM_ForwardGuildCMMsg*) param.param3.GetUserData(); cs::SMGuildJoin respmsg; GuildMgr::Instance()->ForwardGuildSMMsg(param.param1, forward_msg->context(), respmsg); delete forward_msg; delete paging; }; ss::SS_IM_ForwardGuildCMMsg* forward_msg = (ss::SS_IM_ForwardGuildCMMsg*)hdr.user_data; ss::SS_IM_ForwardGuildCMMsg* forward_msg_copy = new ss::SS_IM_ForwardGuildCMMsg(); *forward_msg_copy = *forward_msg; cs::MFPaging* paging_copy = new cs::MFPaging; *paging_copy = msg.paging(); paging_copy->set_curr_page(0); paging_copy->set_page_size(20); a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(guild_id_); std::string fmtstr = "SELECT '' AS account_id"; std::vector sql_params; { sql_params.push_back(a8::XValue(last_apply_idx_)); sql_params.push_back(a8::XValue(guild_id_)); } DBEngine::Instance()->ExecAsyncQuery ( conn_info, ( "SELECT A.idx, A.applyid, A.guild_id, A.sender_id, A.sender_nickname, " " A.sender_avatar_url, A.sender_sex, A.sender_data_version1, " " A.sender_user_value1, A.sender_user_value2, A.sender_user_value3, A.status " "FROM guild_apply A " " LEFT JOIN (" + fmtstr + ") AS B ON B.account_id = A.sender_id " "WHERE A.idx > %d AND A.guild_id='%s' AND A.status=0 AND " " B.account_id IS NULL;" ).c_str(), sql_params, a8::XParams() .SetSender(guild_id_) .SetParam1(hdr.socket_handle) .SetParam2(paging_copy) .SetParam3(forward_msg_copy), on_ok, on_error, guild_id_ ); } void Guild::_CMGuildLog(f8::MsgHdr& hdr, const cs::CMGuildLog& msg) { cs::SMGuildLog respmsg; *respmsg.mutable_paging() = msg.paging(); if (respmsg.paging().page_size() <= 0) { respmsg.mutable_paging()->set_page_size(10); } AdjustPaging(respmsg.mutable_paging(), logdb_->logs().size()); for (int i = respmsg.paging().curr_page() * respmsg.paging().page_size(); i < logdb_->logs().size(); ++i) { #if 0 if (respmsg.member_list().size() >= respmsg.paging().page_size()) { break; } auto p = respmsg.add_member_list(); TypeConvert::Convert(*sorted_members_[i], *p); #endif } } void Guild::FillGuildBasic(cs::MFGuildBasic* guild_basic) { guild_basic->set_guild_id(guild_id_); guild_basic->set_guild_name(guild_name_); guild_basic->set_guild_lv(guild_lv_); guild_basic->set_guild_exp(guild_exp_); guild_basic->set_guild_badge(guild_badge_); guild_basic->set_member_num(member_hash_.size()); guild_basic->set_guild_declaration(guild_declaration_); guild_basic->set_guild_owner_id(owner_id_); guild_basic->set_guild_owner_name(owner_name_); guild_basic->set_guild_owner_avatar_url(owner_avatar_url_); } void Guild::FillGuildDB(ss::MFGuildDB& guild_pb) { for (auto& pair : member_hash_) { auto p = guild_pb.add_members(); TypeConvert::Convert(*pair.second, *p->mutable_base_data()); } } void Guild::SerializeMembers(std::string& guild_members) { a8::MutableXObject* members_xobj = a8::MutableXObject::NewArray(); for (auto& pair : member_hash_) { a8::MutableXObject* member_xobj = a8::MutableXObject::NewObject(); member_xobj->SetVal("account_id", pair.second->account_id); member_xobj->SetVal("nickname", pair.second->nickname); member_xobj->SetVal("guild_job", pair.second->guild_job); members_xobj->Push(*member_xobj); delete member_xobj; } members_xobj->ToJsonStr(guild_members); delete members_xobj; } void Guild::SaveToDB() { std::string guild_data; std::string guild_log; std::string guild_members; { ss::MFGuildDB guild_db; FillGuildDB(guild_db); guild_db.SerializeToString(&guild_data); } { logdb_->SerializeToString(&guild_log); SerializeMembers(guild_members); } auto on_ok = [] (a8::XParams& param, const f8::DataSet* data_set) { }; auto on_error = [] (a8::XParams& param, int error_code, const std::string& error_msg) { }; a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(guild_id_); DBEngine::Instance()->ExecAsyncScript ( conn_info, "UPDATE `guild` SET guild_name='%s', guild_lv=%d, guild_exp=%d, guild_badge=%d, " " guild_apply_num=%d, guild_members='%s', guild_notice='%s', guild_declaration='%s', " " guild_log='%s', owner_id='%s', owner_name='%s', owner_avatar_url='%s', " " creator_id='%s', creator_name='%s', creator_avatar_url='%s', guild_data='%s', guild_status='%d', " " modifytime=%d " "WHERE guild_id=%d;", { guild_name_, guild_lv_, guild_exp_, guild_badge_, guild_apply_num_, guild_members, guild_notice_, guild_declaration_, guild_log, owner_id_, owner_name_, owner_avatar_url_, creator_id_, creator_name_, creator_avatar_url_, guild_data, guild_status_, App::Instance()->nowtime, guild_id_ }, a8::XParams(), on_ok, on_error, guild_id_ ); } void Guild::GenSortedMembers() { sorted_members_.clear(); for (auto& pair : member_hash_) { sorted_members_.push_back(pair.second); } } int Guild::GetMemberNum() { return member_hash_.size(); } void Guild::FillApplyList(const std::string& account_id, cs::MFPaging& paging, cs::SMGuildApplyList& respmsg) { #if 0 RemoveHandledApply(); #endif int i = 0; int start = paging.curr_page() * paging.page_size(); for (auto& pair : apply_hash_) { if (i >= start && i < start + paging.page_size()) { if (pair.second->flag == 1) { continue; } auto apply_pb = respmsg.add_apply_list(); TypeConvert::Convert(*pair.second, *apply_pb); { int target_channel = f8::ExtractChannelIdFromAccountId (apply_pb->base_data().account_id()); int channel = f8::ExtractChannelIdFromAccountId(account_id); App::Instance()->PreProcAvatarUrl (channel, target_channel, *apply_pb->mutable_base_data()->mutable_avatar_url()); } } ++i; } *respmsg.mutable_paging() = paging; if (paging.page_size() > 0) { respmsg.mutable_paging()->set__total_page(ceil(i / paging.page_size())); } else { respmsg.mutable_paging()->set__total_page(1); } } void Guild::ClearApplyBySenderId(const std::string& sender_id) { std::vector deleted_applys; for (auto& pair : apply_hash_) { if (pair.second->base_data.account_id == sender_id) { deleted_applys.push_back(pair.first); } } for (auto idx : deleted_applys) { ClearApplyByIdx(idx); } } void Guild::ClearApplyByIdx(long long idx) { auto itr = apply_hash_.find(idx); if (itr != apply_hash_.end()) { delete itr->second; apply_hash_.erase(itr); } } Guild* Guild::CreateGuild(int gameid, long long guild_id, const std::string& guild_name, int guild_lv, int guild_exp, int guild_badge, int guild_apply_num, const std::string& guild_members, const std::string& guild_notice, const std::string& guild_declaration, const std::string& guild_log, const std::string& owner_id, const std::string& owner_name, const std::string& owner_avatar_url, const std::string& creator_id, const std::string& creator_name, const std::string& creator_avatar_url, const std::string& guild_data, int guild_status, int createtime ) { if (GuildMgr::Instance()->GetGuild(guild_id)) { abort(); } Guild* guild = new Guild; guild->gameid_ = gameid; guild->guild_id_ = guild_id; guild->guild_name_ = guild_name; guild->guild_lv_ = guild_lv; guild->guild_exp_ = guild_exp; guild->guild_badge_ = guild_badge; guild->guild_apply_num_ = guild_apply_num; guild->guild_notice_ = guild_notice; guild->guild_declaration_ = guild_declaration; guild->owner_id_ = owner_id; guild->owner_name_ = owner_name; guild->owner_avatar_url_ = owner_avatar_url; guild->creator_id_ = creator_id; guild->creator_name_ = creator_name; guild->creator_avatar_url_ = creator_avatar_url; guild->guild_status_ = guild_status; guild->createtime_ = createtime; //guild_members guild->Deserialize(guild_data, guild_log); return guild; } void Guild::SendErrorMsg(int socket_handle, const ss::MFIMMsgConext& context, const std::string& errmsg) { cs::SMShowErrorMsg notifymsg; notifymsg.set_msg(errmsg); GuildMgr::Instance()->ForwardGuildSMMsg(socket_handle, context, notifymsg); }