aozhiwei e5c90e2642 1
2020-09-25 14:12:04 +08:00

556 lines
18 KiB
C++

#include "precompile.h"
#include <a8/timer.h>
#include <a8/mutable_xobject.h>
#include "guild.h"
#include "cs_proto.pb.h"
#include "ss_proto.pb.h"
#include "dbengine.h"
#include "app.h"
#include "guildmgr.h"
#include "typeconvert.h"
#include "utils.h"
#include "dbhelper.h"
const int GUILD_MAX_MEMBER_NUM = 50;
void Guild::Init()
{
logdb_ = new ss::MFGuildLogDB;
}
void Guild::UnInit()
{
for (auto& pair : member_hash_) {
delete pair.second;
}
member_hash_.clear();
A8_SAFE_DELETE(logdb_);
for (auto& pair : apply_hash_) {
delete pair.second;
}
}
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& account_id)
{
GuildMember* member = GetMember(account_id);
if (member) {
member_hash_.erase(account_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);
if (!GetMember(forward_msg->context().user_info().base_data().account_id())) {
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;
if (IsFull()) {
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) {
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)) {
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);
if (respmsg.errcode() == 0 &&
!GetMember(forward_msg->context().user_info().base_data().account_id())) {
GuildMember* member = new GuildMember();
TypeConvert::Convert(forward_msg->context().user_info().base_data(), *member);
AddMember(member);
DBHelper::Instance()->SetGuildApplyStatus
(
msg.apply().base_data().account_id(),
guild_id,
1
);
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;
GuildMgr::Instance()->ForwardGuildSMMsg(hdr.socket_handle,
forward_msg->context(),
respmsg);
#if 0
GuildMember* member = GetMember(context.user_info().base_data().account_id());
if (!member) {
return;
}
GuildMgr::Instance()->ForwardGuildSMMsg(socket_handle, context, respmsg);
#endif
}
void Guild::_CMGuildQuit(f8::MsgHdr& hdr, const cs::CMGuildQuit& msg)
{
cs::SMGuildQuit respmsg;
#if 0
GuildMember* member = GetMember(context.user_info().base_data().account_id());
if (!member) {
return;
}
if (member->guild_job == kGuildOwner) {
return;
}
RemoveMember(member->account_id);
GuildMgr::Instance()->ForwardGuildSMMsg(socket_handle, context, respmsg);
#endif
}
void Guild::_CMGuildDismiss(f8::MsgHdr& hdr, const cs::CMGuildDismiss& msg)
{
cs::SMGuildDismiss respmsg;
#if 0
GuildMember* member = GetMember(context.user_info().base_data().account_id());
if (!member) {
return;
}
if (member->guild_job != kGuildOwner) {
return;
}
guild_status = kGuildDismissed;
SaveToDB();
GuildMgr::Instance()->ForwardGuildSMMsg(socket_handle, context, respmsg);
#endif
}
void Guild::_CMGuildRename(f8::MsgHdr& hdr, const cs::CMGuildRename& msg)
{
guild_name = msg.new_name();
cs::SMGuildRename respmsg;
#if 0
GuildMgr::Instance()->ForwardGuildSMMsg(socket_handle, context, respmsg);
MarkDirty();
#endif
}
void Guild::_CMGuildMemberList(f8::MsgHdr& hdr, const cs::CMGuildMemberList& msg)
{
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);
}
#if 0
GuildMgr::Instance()->ForwardGuildSMMsg(socket_handle, context, respmsg);
#endif
}
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<a8::XValue> 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
}
#if 0
GuildMgr::Instance()->ForwardGuildSMMsg(socket_handle, context, respmsg);
#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<long long> 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);
}
}