void ServiceCore::On_MPK_ADDCHAROBJECT(const MessagePack &rstMPK) { AMAddCharObject stAMACO; std::memcpy(&stAMACO, rstMPK.Data(), sizeof(stAMACO)); if(stAMACO.Common.MapID){ if(auto pMap = RetrieveMap(stAMACO.Common.MapID)){ if(false || stAMACO.Common.Random || pMap->In(stAMACO.Common.MapID, stAMACO.Common.X, stAMACO.Common.Y)){ m_ActorPod->Forward(pMap->UID(), {MPK_ADDCHAROBJECT, stAMACO}, [this, stAMACO, rstMPK](const MessagePack &rstRMPK) { switch(rstRMPK.Type()){ case MPK_OK: { m_ActorPod->Forward(rstMPK.From(), MPK_OK, rstMPK.ID()); break; } default: { m_ActorPod->Forward(rstMPK.From(), MPK_ERROR, rstMPK.ID()); break; } } }); return; } } } // invalid location info, return error directly m_ActorPod->Forward(rstMPK.From(), MPK_ERROR, rstMPK.ID()); }
void ServiceCore::On_MPK_QUERYMAPUID(const MessagePack &rstMPK) { AMQueryMapUID stAMQMUID; std::memcpy(&stAMQMUID, rstMPK.Data(), sizeof(stAMQMUID)); if(auto pMap = RetrieveMap(stAMQMUID.MapID)){ AMUID stAMUID; std::memset(&stAMUID, 0, sizeof(stAMUID)); stAMUID.UID = pMap->UID(); m_ActorPod->Forward(rstMPK.From(), {MPK_UID, stAMUID}, rstMPK.ID()); }else{ m_ActorPod->Forward(rstMPK.From(), MPK_ERROR, rstMPK.ID()); } }
void ServiceCore::On_MPK_QUERYMAPLIST(const MessagePack &rstMPK) { AMMapList stAMML; std::memset(&stAMML, 0, sizeof(stAMML)); size_t nIndex = 0; for(auto pMap: m_MapList){ if(pMap.second && pMap.second->ID()){ if(nIndex < (sizeof(stAMML.MapList) / sizeof(stAMML.MapList[0]))){ stAMML.MapList[nIndex++] = pMap.second->ID(); }else{ extern MonoServer *g_MonoServer; g_MonoServer->AddLog(LOGTYPE_FATAL, "Need larger map list size in AMMapList"); g_MonoServer->Restart(); } } } m_ActorPod->Forward(rstMPK.From(), {MPK_MAPLIST, stAMML}, rstMPK.ID()); }
void ServiceCore::On_MPK_QUERYCOCOUNT(const MessagePack &rstMPK) { AMQueryCOCount stAMQCOC; std::memcpy(&stAMQCOC, rstMPK.Data(), sizeof(stAMQCOC)); int nCheckCount = 0; if(stAMQCOC.MapID){ if(m_MapList.find(stAMQCOC.MapID) == m_MapList.end()){ nCheckCount = 0; }else{ nCheckCount = 1; } }else{ nCheckCount = (int)(m_MapList.size()); } switch(nCheckCount){ case 0: { m_ActorPod->Forward(rstMPK.From(), MPK_ERROR, rstMPK.ID()); return; } case 1: { if(auto pMap = (stAMQCOC.MapID ? m_MapList[stAMQCOC.MapID] : m_MapList.begin()->second)){ m_ActorPod->Forward(pMap->UID(), {MPK_QUERYCOCOUNT, stAMQCOC}, [this, rstMPK](const MessagePack &rstRMPK) { switch(rstRMPK.Type()){ case MPK_COCOUNT: { m_ActorPod->Forward(rstMPK.From(), {MPK_COCOUNT, rstRMPK.Data(), rstRMPK.DataLen()}, rstMPK.ID()); return; } case MPK_ERROR: default: { m_ActorPod->Forward(rstMPK.From(), MPK_ERROR, rstMPK.ID()); return; } } }); return; }else{ m_MapList.erase(stAMQCOC.MapID); m_ActorPod->Forward(rstMPK.From(), MPK_ERROR, rstMPK.ID()); return; } } default: { // difficult part // need send multiple query message and collect them // after all collected we need to return the sum, problem: // 1. share state // 2. error handle struct SharedState { bool Done; int CheckCount; int COCount; SharedState(int nCheckCount) : Done(false) , CheckCount(nCheckCount) , COCount(0) {} }; // current I don't have error handling // means if one query didn't get responded it will wait forever // to solve this issue, we can install an state hook but for simplity not now auto pSharedState = std::make_shared<SharedState>(nCheckCount); auto fnOnResp = [pSharedState, this, rstMPK](const MessagePack &rstRMPK) { switch(rstRMPK.Type()){ case MPK_COCOUNT: { if(pSharedState->Done){ // we get response but shared state shows ``done" // means more than one error has alreay happened before // do nothing }else{ // get one more valid response // need to check if we need to response to sender AMCOCount stAMCOC; std::memcpy(&stAMCOC, rstRMPK.Data(), sizeof(stAMCOC)); if(pSharedState->CheckCount == 1){ stAMCOC.Count += pSharedState->COCount; m_ActorPod->Forward(rstMPK.From(), {MPK_COCOUNT, stAMCOC}, rstMPK.ID()); }else{ pSharedState->CheckCount--; pSharedState->COCount += (int)(stAMCOC.Count); } } return; } case MPK_ERROR: default: { if(pSharedState->Done){ // we get response but shared state shows ``done" // means more than one error has alreay happened before // do nothing }else{ // get first error m_ActorPod->Forward(rstMPK.From(), MPK_ERROR, rstMPK.ID()); } return; } } }; for(auto p: m_MapList){ m_ActorPod->Forward(p.second->UID(), {MPK_QUERYCOCOUNT, stAMQCOC}, fnOnResp); } return; } } }