int RespondPrefGet(PreferenceContainer *prefSet, char *SendBuf, SimulatorQuery *query) { //Helper function for the "pref.getA" and "pref.get" queries. //Since the both accounts and characters use the same class to store //preferences, the query handlers will call this function with the //appropriate pointer. int WritePos = 0; WritePos += PutByte(&SendBuf[WritePos], 1); //_handleQueryResultMsg WritePos += PutShort(&SendBuf[WritePos], 0); //Message size WritePos += PutInteger(&SendBuf[WritePos], query->ID); //Query response index //Each preference request will have a matching response field. WritePos += PutShort(&SendBuf[WritePos], query->argCount); for (unsigned int i = 0; i < query->argCount; i++) { const char * pref = prefSet->GetPrefValue(query->args[i].c_str()); //One string for each preference result. WritePos += PutByte(&SendBuf[WritePos], 1); if (pref != NULL) { WritePos += PutStringUTF(&SendBuf[WritePos], pref); } else { WritePos += PutStringUTF(&SendBuf[WritePos], ""); } } PutShort(&SendBuf[1], WritePos - 3); return WritePos; }
int PartyManager :: WriteLootRoll(char *outbuf, const char *itemDefName, char roll, const char *bidder) { int wpos = 0; wpos += PutByte(&outbuf[wpos], 6); //_handlePartyUpdateMsg wpos += PutShort(&outbuf[wpos], 0); wpos += PutByte(&outbuf[wpos], PartyUpdateOpTypes::LOOT_ROLL); wpos += PutStringUTF(&outbuf[wpos], itemDefName); wpos += PutByte(&outbuf[wpos], roll); wpos += PutStringUTF(&outbuf[wpos], bidder); PutShort(&outbuf[1], wpos - 3); //Set message size return wpos; }
int PrepExt_QueryResponseString2(char *buffer, int queryIndex, const char *strData1, const char *strData2) { int wpos = 0; wpos += PutByte(&buffer[wpos], 1); //_handleQueryResultMsg wpos += PutShort(&buffer[wpos], 0); //Placeholder for message size wpos += PutInteger(&buffer[wpos], queryIndex); //Query response index wpos += PutShort(&buffer[wpos], 1); //Row count wpos += PutByte(&buffer[wpos], 2); //String count wpos += PutStringUTF(&buffer[wpos], strData1); //String data wpos += PutStringUTF(&buffer[wpos], strData2); //String data PutShort(&buffer[1], wpos - 3); //Message size return wpos; }
int PrepExt_CreatureEventPortalRequest(char *buffer, int actorID, const char *casterName, const char *locationName) { int wpos = 0; wpos += PutByte(&buffer[wpos], 4); //_handleCreatureEventMsg wpos += PutShort(&buffer[wpos], 0); wpos += PutInteger(&buffer[wpos], actorID); wpos += PutByte(&buffer[wpos], 24); //event to request a portal wpos += PutStringUTF(&buffer[wpos], casterName); wpos += PutStringUTF(&buffer[wpos], locationName); PutShort(&buffer[1], wpos - 3); //Set message size return wpos; }
int PartyManager :: WriteLootWin(char *outbuf, const char *lootTag, const char *originalTag, const char *winner, int creatureId, int slotIndex) { int wpos = 0; wpos += PutByte(&outbuf[wpos], 6); //_handlePartyUpdateMsg wpos += PutShort(&outbuf[wpos], 0); wpos += PutByte(&outbuf[wpos], PartyUpdateOpTypes::LOOT_WIN); wpos += PutStringUTF(&outbuf[wpos], lootTag); wpos += PutStringUTF(&outbuf[wpos], originalTag); wpos += PutStringUTF(&outbuf[wpos], winner); char buf[34]; Util::SafeFormat(buf, sizeof(buf), "%d:%d", creatureId, slotIndex); wpos += PutStringUTF(&outbuf[wpos], buf); PutShort(&outbuf[1], wpos - 3); //Set message size return wpos; }
int PrepExt_QueryResponseMultiString(char *buffer, int queryIndex, const MULTISTRING &strData) { int wpos = 0; wpos += PutByte(&buffer[wpos], 1); //_handleQueryResultMsg wpos += PutShort(&buffer[wpos], 0); //Placeholder for message size wpos += PutInteger(&buffer[wpos], queryIndex); //Query response index size_t rowCount = strData.size(); size_t stringCount; wpos += PutShort(&buffer[wpos], rowCount); for(size_t rows = 0; rows < rowCount; rows++) { stringCount = strData[rows].size(); if(stringCount > 255) { g_Logs.server->warn("PrepExt_QueryResponseMultiString too many strings: %v", stringCount); stringCount = 255; } wpos += PutByte(&buffer[wpos], stringCount); for(size_t str = 0; str < stringCount; str++) { //g_Log.AddMessageFormat("[DEBUG] [%d][%d]=%s", rows, str, strData[rows][str].c_str()); wpos += PutStringUTF(&buffer[wpos], strData[rows][str].c_str()); //String data } } PutShort(&buffer[1], wpos - 3); return wpos; }
int PartyManager :: WriteMemberList(char *outbuf, ActiveParty *party, int memberID) { //memberID is the creature ID that is requesting the list. //The client needs this to determine if it's leading the party. int wpos = 0; wpos += PutByte(&outbuf[wpos], 6); //_handlePartyUpdateMsg wpos += PutShort(&outbuf[wpos], 0); wpos += PutByte(&outbuf[wpos], PartyUpdateOpTypes::JOINED_PARTY); //wpos += PutByte(&outbuf[wpos], party->mMemberList.size()); int countLoc = wpos; wpos += PutByte(&outbuf[wpos], 0); wpos += PutInteger(&outbuf[wpos], party->mLeaderID); wpos += PutInteger(&outbuf[wpos], memberID); //memberId int count = 0; for(size_t i = 0; i < party->mMemberList.size(); i++) { if(party->mMemberList[i].mCreatureID != memberID) { wpos += PutInteger(&outbuf[wpos], party->mMemberList[i].mCreatureID); wpos += PutStringUTF(&outbuf[wpos], party->mMemberList[i].mDisplayName.c_str()); count++; } } PutByte(&outbuf[countLoc], count); PutShort(&outbuf[1], wpos - 3); //Set message size return wpos; }
int PartyManager :: WriteProposeInvite(char *outbuf, int proposeeId, const char *proposeeName, int proposerId, const char *proposerName) { int wpos = 0; wpos += PutByte(&outbuf[wpos], 6); //_handlePartyUpdateMsg wpos += PutShort(&outbuf[wpos], 0); wpos += PutByte(&outbuf[wpos], PartyUpdateOpTypes::PROPOSE_INVITE); wpos += PutInteger(&outbuf[wpos], proposeeId); wpos += PutStringUTF(&outbuf[wpos], proposeeName); wpos += PutInteger(&outbuf[wpos], proposerId); wpos += PutStringUTF(&outbuf[wpos], proposerName); PutShort(&outbuf[1], wpos - 3); //Set message size return wpos; }
int PrepExt_SendTimeOfDayMsg(char *buffer, const char *envType) { int wpos = 0; wpos += PutByte(&buffer[wpos], 42); //_handleEnvironmentUpdateMsg wpos += PutShort(&buffer[wpos], 0); wpos += PutByte(&buffer[wpos], 2); //Mask: Time of day update event wpos += PutStringUTF(&buffer[wpos], ""); //zoneIDString wpos += PutInteger(&buffer[wpos], 0); //zoneDefID wpos += PutShort(&buffer[wpos], 0); //zonePageSize wpos += PutStringUTF(&buffer[wpos], ""); //Terrain wpos += PutStringUTF(&buffer[wpos], envType); //envtype wpos += PutStringUTF(&buffer[wpos], ""); //mapName PutShort(&buffer[1], wpos - 3); //Set message size return wpos; }
int PartyManager :: WriteRejectInvite(char *outbuf, const char *memberDenied) { int wpos = 0; wpos += PutByte(&outbuf[wpos], 6); //_handlePartyUpdateMsg wpos += PutShort(&outbuf[wpos], 0); wpos += PutByte(&outbuf[wpos], PartyUpdateOpTypes::INVITE_REJECTED); wpos += PutStringUTF(&outbuf[wpos], memberDenied); PutShort(&outbuf[1], wpos - 3); //Set message size return wpos; }
int PrepExt_GenericChatMessage(char *buffer, int creatureID, const char *name, const char *channel, const char *message) { //Handles a "communicate" (0x04) message containing a channel and string //Sends back a "_handleCommunicationMsg" (50 = 0x32) to the client //Ideally this function should broadcast the message to all active player threads //in the future so that all players can receive the communication message. int wpos = 0; wpos += PutByte(&buffer[wpos], 0x32); //_handleCommunicationMsg wpos += PutShort(&buffer[wpos], 0); //Placeholder for size wpos += PutInteger(&buffer[wpos], creatureID); //Character ID who's sending the message wpos += PutStringUTF(&buffer[wpos], name); //Character name wpos += PutStringUTF(&buffer[wpos], channel); //channel type wpos += PutStringUTF(&buffer[wpos], message); //message body PutShort(&buffer[1], wpos - 3); //Set size return wpos; }
int PrepExt_QueryResponseError(char *buffer, int queryIndex, const char *message) { int wpos = 0; wpos += PutByte(&buffer[wpos], 1); //_handleQueryResultMsg wpos += PutShort(&buffer[wpos], 0); //Placeholder for message size wpos += PutInteger(&buffer[wpos], queryIndex); //Query response index wpos += PutShort(&buffer[wpos], 0x7000); //Negative number indicates error wpos += PutStringUTF(&buffer[wpos], message); //String data PutShort(&buffer[1], wpos - 3); //Message size return wpos; }
int PartyManager :: WriteInCharge(char *outbuf, ActiveParty *party) { int wpos = 0; wpos += PutByte(&outbuf[wpos], 6); //_handlePartyUpdateMsg wpos += PutShort(&outbuf[wpos], 0); wpos += PutByte(&outbuf[wpos], PartyUpdateOpTypes::IN_CHARGE); wpos += PutInteger(&outbuf[wpos], party->mLeaderID); wpos += PutStringUTF(&outbuf[wpos], party->mLeaderName.c_str()); PutShort(&outbuf[1], wpos - 3); //Set message size return wpos; }
int PrepExt_SetTimeOfDay(char *buffer, char *envType) { int wpos = 0; wpos += PutByte(&buffer[wpos], 42); //_handleEnvironmentUpdateMsg wpos += PutShort(&buffer[wpos], 0); wpos += PutByte(&buffer[wpos], 2); //Mask for time of day update wpos += PutStringUTF(&buffer[wpos], ""); //zoneID wpos += PutInteger(&buffer[wpos], 0); //zoneDefID wpos += PutShort(&buffer[wpos], 0); //zonePageSize wpos += PutStringUTF(&buffer[wpos], ""); //Terrain wpos += PutStringUTF(&buffer[wpos], envType); //envtype //When the mask is 2, the function changes the time of day using the EnvironmentType string //the function returns from that point and never gets to the rest of the map stuff. PutShort(&buffer[1], wpos - 3); //Set message size return wpos; }
int PartyManager :: WriteQuestInvite(char *outbuf, const char* questName, int questID) { int wpos = 0; wpos += PutByte(&outbuf[wpos], 6); //_handlePartyUpdateMsg wpos += PutShort(&outbuf[wpos], 0); wpos += PutByte(&outbuf[wpos], PartyUpdateOpTypes::QUEST_INVITE); wpos += PutStringUTF(&outbuf[wpos], questName); wpos += PutInteger(&outbuf[wpos], questID); PutShort(&outbuf[1], wpos - 3); //Set message size return wpos; }
int PrepExt_SendInfoMessage(char *buffer, const char *message, unsigned char eventID) { int wpos = 0; wpos += PutByte(&buffer[wpos], 0); //_handleInfoMsg wpos += PutShort(&buffer[wpos], 0); //Placeholder for size wpos += PutStringUTF(&buffer[wpos], message); wpos += PutByte(&buffer[wpos], eventID); //Event type for error message PutShort(&buffer[1], wpos - 3); //Set size return wpos; }
int PrepExt_CancelUseEvent(char *buffer, int CreatureID) { int wpos = 0; wpos += PutByte(&buffer[wpos], 4); //_handleCreatureEventMsg wpos += PutShort(&buffer[wpos], 0); //size wpos += PutInteger(&buffer[wpos], CreatureID); wpos += PutByte(&buffer[wpos], 11); //creature "used" event wpos += PutStringUTF(&buffer[wpos], ""); wpos += PutFloat(&buffer[wpos], -1.0F); //A delay of -1 will interrupt the action PutShort(&buffer[1], wpos - 3); //size return wpos; }
int PrepExt_Broadcast(char *buffer, const char *message) { int wpos = 0; wpos += PutByte(&buffer[wpos], 0); //_handleInfoMsg wpos += PutShort(&buffer[wpos], 0); //Placeholder for size wpos += PutStringUTF(&buffer[wpos], message); wpos += PutByte(&buffer[wpos], 14); //Event type for broadcast PutShort(&buffer[1], wpos - 3); //Set size return wpos; }
int PrepExt_SendFallDamage(char *buffer, int damage) { int wpos = 0; wpos += PutByte(&buffer[wpos], 0); //_handleInfoMsg wpos += PutShort(&buffer[wpos], 0); //Placeholder for size wpos += PutStringUTF(&buffer[wpos], ""); //Unused? wpos += PutByte(&buffer[wpos], 11); //Event type for fall damage message wpos += PutInteger(&buffer[wpos], damage); PutShort(&buffer[1], wpos - 3); //Set size return wpos; }
int PartyManager :: OfferLoot(char *outbuf, int itemDefID, const char *lootTag, bool needed) { int wpos = 0; wpos += PutByte(&outbuf[wpos], 6); //_handlePartyUpdateMsg wpos += PutShort(&outbuf[wpos], 0); wpos += PutByte(&outbuf[wpos], PartyUpdateOpTypes::OFFER_LOOT); wpos += PutStringUTF(&outbuf[wpos], lootTag); wpos += PutInteger(&outbuf[wpos], itemDefID);; wpos += PutByte(&outbuf[wpos], needed ? 1 : 0); PutShort(&outbuf[1], wpos - 3); //Set message size return wpos; }
int PrepExt_CooldownExpired(char *buffer, long actor, const char *cooldownCategory) { int wpos = 0; wpos += PutByte(&buffer[wpos], 4); //_handleCreatureEventMsg wpos += PutShort(&buffer[wpos], 0); wpos += PutInteger(&buffer[wpos], actor); //actorID wpos += PutByte(&buffer[wpos], 22); //22 = Cooldown category expired wpos += PutStringUTF(&buffer[wpos], cooldownCategory); PutShort(&buffer[1], wpos - 3); //Set message size return wpos; }
int PrepExt_SendAdvancedEmote(char *buffer, int creatureID, const char *emoteName, float emoteSpeed, int loop) { int wpos = 0; wpos += PutByte(&buffer[wpos], 100); //_handleModMessage REQUIRES MODDED CLIENT wpos += PutShort(&buffer[wpos], 0); //Reserve for size wpos += PutByte(&buffer[wpos], MODMESSAGE_EVENT_EMOTE); //event for advanced emote wpos += PutInteger(&buffer[wpos], creatureID); wpos += PutStringUTF(&buffer[wpos], emoteName); wpos += PutFloat(&buffer[wpos], emoteSpeed); wpos += PutByte(&buffer[wpos], (loop != 0)); PutShort(&buffer[1], wpos - 3); //Set message size return wpos; }
void PartyManager :: BroadcastAddMember(CreatureInstance* member) { //Generates a packet for a new member notification and broadcasts it to //all other players in the party. ActiveParty *party = GetPartyByID(member->PartyID); if(party == NULL) return; int wpos = 0; wpos += PutByte(&WriteBuf[wpos], 6); //_handlePartyUpdateMsg wpos += PutShort(&WriteBuf[wpos], 0); wpos += PutByte(&WriteBuf[wpos], PartyUpdateOpTypes::ADD_MEMBER); wpos += PutInteger(&WriteBuf[wpos], member->CreatureID); wpos += PutStringUTF(&WriteBuf[wpos], member->css.display_name); PutShort(&WriteBuf[1], wpos - 3); //Set message size party->BroadCastExcept(WriteBuf, wpos, member->CreatureDefID); }
int PrepExt_SendEffect(char *buffer, int sourceID, const char *effectName, int targetID) { //Send an effect to the client. Send as a single target effect //unless targetID is nonzero. int wpos = 0; wpos += PutByte(&buffer[wpos], 4); //_handleCreatureEventMsg wpos += PutShort(&buffer[wpos], 0); //Reserve for size wpos += PutInteger(&buffer[wpos], sourceID); wpos += PutByte(&buffer[wpos], (targetID == 0) ? 4 : 12); //Cue effect wpos += PutStringUTF(&buffer[wpos], effectName); if(targetID != 0) wpos += PutInteger(&buffer[wpos], targetID); PutShort(&buffer[1], wpos - 3); //Set message size return wpos; }
int PrepExt_QueryResponseStringList(char *buffer, int queryIndex, const STRINGLIST &strData) { int wpos = 0; wpos += PutByte(&buffer[wpos], 1); //_handleQueryResultMsg wpos += PutShort(&buffer[wpos], 0); //Placeholder for message size wpos += PutInteger(&buffer[wpos], queryIndex); //Query response index wpos += PutShort(&buffer[wpos], 1); //Row count int count = strData.size(); if(count > 255) { g_Logs.server->warn("PrepExt_QueryResponseStringList too many strings: %v", count); count = 255; } wpos += PutByte(&buffer[wpos], count); //String count for(int a = 0; a < count; a++) wpos += PutStringUTF(&buffer[wpos], strData[a].c_str()); //String data PutShort(&buffer[1], wpos - 3); //Message size return wpos; }
bool ChatManager::DeliverChatMessage(ChatMessage &message, CreatureInstance *sendingCreatureInstance) { message.mTime = time(NULL); int wpos = 0; wpos += PutByte(&SendBuf[wpos], 50); //_handleCommunicationMsg wpos += PutShort(&SendBuf[wpos], 0); //Placeholder for size wpos += PutInteger(&SendBuf[wpos], message.mSenderCreatureID); //Character ID who's sending the message wpos += PutStringUTF(&SendBuf[wpos], message.mSender.c_str()); //pld.charPtr->cdef.css.display_name); //Character name wpos += PutStringUTF(&SendBuf[wpos], message.mTell ? "t/" : message.mChannel->channel); wpos += PutStringUTF(&SendBuf[wpos], message.mMessage.c_str()); PutShort(&SendBuf[1], wpos - 3); //Set size bool found = false; bool log = !message.mTell && ( message.mChannel->chatScope == CHAT_SCOPE_REGION || message.mChannel->chatScope == CHAT_SCOPE_SERVER ); bool breakLoop = false; SIMULATOR_IT it; for(it = Simulator.begin(); it != Simulator.end(); ++it) { if(breakLoop == true) break; if(it->ProtocolState == 0) { //LogMessageL(MSG_ERROR, "[WARNING] Cannot not send chat to lobby protocol simulator"); continue; } if(it->isConnected == false) continue; if(it->pld.charPtr == NULL) continue; bool send = false; if(message.mTell == true) { if(strcmp(it->pld.charPtr->cdef.css.display_name, message.mRecipient.c_str()) == 0) { send = true; found = true; } } else { switch(message.mChannel->chatScope) { case CHAT_SCOPE_LOCAL: if(sendingCreatureInstance == NULL || it->pld.CurrentInstanceID != message.mSendingInstance) break; if(ActiveInstance::GetPlaneRange(it->creatureInst, sendingCreatureInstance, LOCAL_CHAT_RANGE) > LOCAL_CHAT_RANGE) break; send = true; break; case CHAT_SCOPE_REGION: if(it->pld.CurrentInstanceID != message.mSendingInstance) break; send = true; break; case CHAT_SCOPE_SERVER: send = true; if(message.mChannelName.compare("gm/earthsages") == 0 && !it->pld.accPtr->HasPermission(Perm_Account, Permission_GMChat) && !it->pld.accPtr->HasPermission(Perm_Account, Permission_Admin)) { send = false; } break; case CHAT_SCOPE_FRIEND: if(it->pld.CreatureDefID == message.mSenderCreatureDefID) //Send to self send = true; else if(g_FriendListManager.IsMutualFriendship(it->pld.CreatureDefID, message.mSenderCreatureDefID) ==true) send = true; break; case CHAT_SCOPE_CHANNEL: { PrivateChannel *privateChannelData = g_ChatChannelManager.GetChannelForMessage(message.mSimulatorID, message.mChannelName.c_str() + 3); if(privateChannelData != NULL) { for(size_t i = 0; i < privateChannelData->mMemberList.size(); i++) if(it->InternalID == privateChannelData->mMemberList[i].mSimulatorID) send = true; } break; } case CHAT_SCOPE_PARTY: if(sendingCreatureInstance == NULL) break; g_PartyManager.BroadCastPacket(sendingCreatureInstance->PartyID, sendingCreatureInstance->CreatureDefID, SendBuf, wpos); breakLoop = true; break; case CHAT_SCOPE_CLAN: { Clans::Clan c = g_ClanManager.GetClan(message.mSenderClanID); if(it->pld.CreatureDefID == message.mSenderCreatureDefID) //Send to self send = true; else { if(c.mId > 0 && it->pld.charPtr->clan == c.mId) send = true; else if(g_GuildManager.IsMutualGuild(it->pld.CreatureDefID, message.mSenderCreatureDefID) ==true) send = true; } break; } default: break; } } if(send == true) { found = true; it->AttemptSend(SendBuf, wpos); } } if(log == true) LogChatMessage(message); return found; }
int ChatManager :: handleCommunicationMsg(char *channel, char *message, char *name) { //Returns the number of bytes composing the message data. //Mostly copied from the Simulator function with the same name, but without permissions //checks. To be used internally by the server when it needs to send arbitrary messages //to clients. Should not be used for /tell messages. //Handles a "communicate" (0x04) message containing a channel and string //Sends back a "_handleCommunicationMsg" (50 = 0x32) to the client //Ideally this function should broadcast the message to all active player threads //in the future so that all players can receive the communication message. char ComBuf[1024]; char LogBuffer[1024]; if(strlen(channel) == 0 || strlen(message) == 0) return 0; //LogMessageL("[%s]:[%s]", channel, message); /* bool log = false; char *prefix = NULL; if(strcmp(channel, "s") == 0) { log = true; prefix = ChatPrefix_Say; } else if(strcmp(channel, "gm/earthsages") == 0) { log = true; prefix = ChatPrefix_GM; } else if(strcmp(channel, "*SysChat") == 0) { log = true; prefix = ChatPrefix_SysChat; } else if(strcmp(channel, "rc/") == 0) { log = true; prefix = ChatPrefix_Region; } if(log == true) { if(prefix != NULL) sprintf(LogBuffer, "%s %s: %s", prefix, name, message); else sprintf(LogBuffer, "%s: %s", name, message); LogChatMessage(LogBuffer); } else { sprintf(LogBuffer, "%s: %s", name, message); LogChatMessage(LogBuffer); }*/ int found = 0; int a; for(a = 1; a < NumValidChatChannel; a++) { if(strcmp(ValidChatChannel[a].channel, channel) == 0) { found = a; break; } } int wpos = 0; if(ValidChatChannel[found].prefix != NULL) wpos += sprintf(&LogBuffer[wpos], "%s ", ValidChatChannel[found].prefix); if(ValidChatChannel[found].name == true) wpos += sprintf(&LogBuffer[wpos], "%s: ", name); else name[0] = 0; //Disable name from showing in the data buffer wpos += sprintf(&LogBuffer[wpos], "%s", message); ChatMessage cm(message); LogChatMessage(cm); wpos = 0; wpos += PutByte(&ComBuf[wpos], 0x32); //_handleCommunicationMsg wpos += PutShort(&ComBuf[wpos], 0); //Placeholder for size wpos += PutInteger(&ComBuf[wpos], 0); //Character ID who's sending the message wpos += PutStringUTF(&ComBuf[wpos], name); //Character name wpos += PutStringUTF(&ComBuf[wpos], channel); //return the channel type wpos += PutStringUTF(&ComBuf[wpos], message); //return the message PutShort(&ComBuf[1], wpos - 3); //Set size SIMULATOR_IT it; for(it = Simulator.begin(); it != Simulator.end(); ++it) { if(it->isConnected == true) it->AttemptSend(ComBuf, wpos); } return wpos; }
int PersonaListHandler::handleQuery(SimulatorThread *sim, CharacterServerData *pld, SimulatorQuery *query, CreatureInstance *creatureInstance) { /* Query: persona.list Args : [none] Notes: First query sent to the server. Response: Send back the list of characters available on this account. */ //Seems to be a rare condition when the account can indeed be NULL at this point. Possibly //disconnecting after the query is sent, but before it's processed? if (pld->accPtr == NULL) { g_Logs.simulator->error("[%v] persona.list null account", sim->InternalID); return 0; } g_Logs.simulator->info("Retrieving persona list for account:%v", pld->accPtr->ID); //TODO: Fix a potential buffer overflow. int WritePos = 0; WritePos += PutByte(&sim->SendBuf[WritePos], 1); //_handleQueryResultMsg WritePos += PutShort(&sim->SendBuf[WritePos], 0); //Message size WritePos += PutInteger(&sim->SendBuf[WritePos], query->ID); //Query ID //Character row count int charCount = pld->accPtr->GetCharacterCount(); if (g_ProtocolVersion >= 38) { //Version 0.8.9 has a an extra row in the beginning //with one string, the number of characters following. WritePos += PutShort(&sim->SendBuf[WritePos], charCount + 1); WritePos += PutByte(&sim->SendBuf[WritePos], 1); sprintf(sim->Aux3, "%d", charCount + 1); WritePos += PutStringUTF(&sim->SendBuf[WritePos], sim->Aux3); } else { WritePos += PutShort(&sim->SendBuf[WritePos], charCount); } g_CharacterManager.GetThread("SimulatorThread::handle_query_persona_list"); int b; for (b = 0; b < AccountData::MAX_CHARACTER_SLOTS; b++) { if (pld->accPtr->CharacterSet[b] != 0) { int cdefid = pld->accPtr->CharacterSet[b]; CharacterCacheEntry *cce = pld->accPtr->characterCache.ForceGetCharacter(cdefid); if (cce == NULL) { g_Logs.simulator->error("[%v] Could not request character: %v", sim->InternalID, cdefid); sim->ForceErrorMessage("Critical: could not load a character.", INFOMSG_ERROR); sim->Disconnect("SimulatorThread::handle_query_persona_list"); return 0; } if (g_Config.AprilFools != 0) { WritePos += PutByte(&sim->SendBuf[WritePos], 6); //6 character data strings WritePos += PutStringUTF(&sim->SendBuf[WritePos], cce->display_name.c_str()); //Seems to be sent twice in 0.8.9. Unknown purpose. WritePos += PutStringUTF(&sim->SendBuf[WritePos], cce->display_name.c_str()); WritePos += PutStringUTF(&sim->SendBuf[WritePos], cce->appearance.c_str()); const char *eqApp = cce->eq_appearance.c_str(); switch (cce->profession) { case 1: eqApp = "{[1]=3163,[0]=141760,[6]=3019,[10]=3008,[11]=2831}"; break; case 2: eqApp = "{[0]=141763,[1]=141764,[6]=2107,[10]=2442,[11]=2898}"; break; case 3: eqApp = "{[6]=2810,[10]=1980,[11]=2108,[2]=141765}"; break; case 4: eqApp = "{[2]=143609,[6]=3160,[10]=3161,[11]=3162}"; break; } WritePos += PutStringUTF(&sim->SendBuf[WritePos], eqApp); //sprintf(Aux3, "%d", cce->level); WritePos += PutStringUTF(&sim->SendBuf[WritePos], "1"); sprintf(sim->Aux3, "%d", cce->profession); WritePos += PutStringUTF(&sim->SendBuf[WritePos], sim->Aux3); if (WritePos >= (int) sizeof(sim->SendBuf)) g_Logs.server->error("Buffer overflow in persona.list"); } else { //Normal stuff. WritePos += PutByte(&sim->SendBuf[WritePos], 6); //6 character data strings WritePos += PutStringUTF(&sim->SendBuf[WritePos], cce->display_name.c_str()); //Seems to be sent twice in 0.8.9. Unknown purpose. WritePos += PutStringUTF(&sim->SendBuf[WritePos], cce->display_name.c_str()); WritePos += PutStringUTF(&sim->SendBuf[WritePos], cce->appearance.c_str()); WritePos += PutStringUTF(&sim->SendBuf[WritePos], cce->eq_appearance.c_str()); sprintf(sim->Aux3, "%d", cce->level); WritePos += PutStringUTF(&sim->SendBuf[WritePos], sim->Aux3); sprintf(sim->Aux3, "%d", cce->profession); WritePos += PutStringUTF(&sim->SendBuf[WritePos], sim->Aux3); if (WritePos >= (int) sizeof(sim->SendBuf)) g_Logs.server->error("Buffer overflow in persona.list"); } } } PutShort(&sim->SendBuf[1], WritePos - 3); //Set message size g_CharacterManager.ReleaseThread(); return WritePos; }
void SceneryManager::SendPageRequest(const SceneryPageRequest& request, std::list<PacketManager::PACKET_PAIR>& outgoingPackets) { TimeObject to("SceneryManager::SendPageRequest"); STRINGLIST queryRows; Packet data; int wpos = 0; char idBuf[32]; GetThread("SceneryManager::HandlePageRequests[page]"); SceneryPage *page = GetOrCreatePage(request.zone, request.x, request.y); if(page == NULL) { g_Log.AddMessageFormat("[ERROR] SendPageRequest retrieved NULL page"); wpos = PrepExt_QueryResponseNull(prepBuf, request.queryID); data.Assign(prepBuf, wpos); outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data)); ReleaseThread(); return; } SceneryPage::SCENERY_IT it; for(it = page->mSceneryList.begin(); it != page->mSceneryList.end(); ++it) { //Build the list of scenery ID strings to form the response to the scenery.list query. //No need to save row data unless the query is required. if(request.skipQuery == false) { sprintf(idBuf, "%d", it->second.ID); queryRows.push_back(idBuf); } wpos += PrepExt_UpdateScenery(&prepBuf[wpos], &it->second); if(wpos > Global::MAX_SEND_CHUNK_SIZE) { data.Assign(prepBuf, wpos); outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data)); wpos = 0; } } if(wpos > 0) { data.Assign(prepBuf, wpos); outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data)); } //Done accessing the scenery data itself, no need to hold the thread any longer. //All the remaining stuff is using a resident list of query IDs to form into a response //packet. ReleaseThread(); //Now build the query response if the client has requested it. if(request.skipQuery == true) return; //Reset the packet buffer and data. wpos = 0; data.Clear(); //Get the size of the response int sizeReq = 6; //Query ID (4 bytes) + row count (2 bytes) for(size_t s = 0; s < queryRows.size(); s++) { sizeReq++; //1 string per row sizeReq += PutStringReq(queryRows[s].c_str()); } wpos += PutByte(&prepBuf[wpos], 1); //_handleQueryResultMsg wpos += PutShort(&prepBuf[wpos], sizeReq); //Message size wpos += PutInteger(&prepBuf[wpos], request.queryID); wpos += PutShort(&prepBuf[wpos], queryRows.size()); for(size_t s = 0; s < queryRows.size(); s++) { wpos += PutByte(&prepBuf[wpos], 1); wpos += PutStringUTF(&prepBuf[wpos], queryRows[s].c_str()); if(wpos > Global::MAX_SEND_CHUNK_SIZE) { data.Append(prepBuf, wpos); wpos = 0; } } if(wpos > 0) data.Append(prepBuf, wpos); outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data)); }
int PrepExt_ItemDef(char *SendBuf, ItemDef *item, int ProtocolState) { int WritePos = 0; //_handleItemDefUpdateMsg is [4] for lobby, [71] for play (most common) protocol char message = 71; if(ProtocolState == 0) message = 4; WritePos += PutByte(&SendBuf[WritePos], message); WritePos += PutShort(&SendBuf[WritePos], 0); //Message size WritePos += PutInteger(&SendBuf[WritePos], item->mID); //Fill the item properties WritePos += PutByte(&SendBuf[WritePos], item->mType); WritePos += PutStringUTF(&SendBuf[WritePos], item->mDisplayName.c_str()); WritePos += PutStringUTF(&SendBuf[WritePos], item->mAppearance.c_str()); WritePos += PutStringUTF(&SendBuf[WritePos], item->mIcon.c_str()); WritePos += PutByte(&SendBuf[WritePos], item->mIvType1); WritePos += PutShort(&SendBuf[WritePos], item->mIvMax1); WritePos += PutByte(&SendBuf[WritePos], item->mIvType2); WritePos += PutShort(&SendBuf[WritePos], item->mIvMax2); WritePos += PutStringUTF(&SendBuf[WritePos], item->mSv1.c_str()); if(g_ProtocolVersion < 5) WritePos += PutInteger(&SendBuf[WritePos], item->_mCopper); WritePos += PutShort(&SendBuf[WritePos], item->mContainerSlots); WritePos += PutByte(&SendBuf[WritePos], item->mAutoTitleType); WritePos += PutShort(&SendBuf[WritePos], item->mLevel); WritePos += PutByte(&SendBuf[WritePos], item->mBindingType); WritePos += PutByte(&SendBuf[WritePos], item->mEquipType); WritePos += PutByte(&SendBuf[WritePos], item->mWeaponType); if(item->mWeaponType != 0) { if(g_ProtocolVersion == 7) { WritePos += PutByte(&SendBuf[WritePos], item->mWeaponDamageMin); WritePos += PutByte(&SendBuf[WritePos], item->mWeaponDamageMax); WritePos += PutByte(&SendBuf[WritePos], item->_mSpeed); WritePos += PutByte(&SendBuf[WritePos], item->mWeaponExtraDamangeRating); WritePos += PutByte(&SendBuf[WritePos], item->mWeaponExtraDamageType); } else { WritePos += PutInteger(&SendBuf[WritePos], item->mWeaponDamageMin); WritePos += PutInteger(&SendBuf[WritePos], item->mWeaponDamageMax); WritePos += PutByte(&SendBuf[WritePos], item->mWeaponExtraDamangeRating); WritePos += PutByte(&SendBuf[WritePos], item->mWeaponExtraDamageType); } } WritePos += PutInteger(&SendBuf[WritePos], item->mEquipEffectId); WritePos += PutInteger(&SendBuf[WritePos], item->mUseAbilityId); WritePos += PutInteger(&SendBuf[WritePos], item->mActionAbilityId); WritePos += PutByte(&SendBuf[WritePos], item->mArmorType); if(item->mArmorType != 0) { if(g_ProtocolVersion == 7) { WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistMelee); WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistFire); WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistFrost); WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistMystic); WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistDeath); } else { WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistMelee); WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistFire); WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistFrost); WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistMystic); WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistDeath); } } if(g_ProtocolVersion == 7) { WritePos += PutByte(&SendBuf[WritePos], item->mBonusStrength); WritePos += PutByte(&SendBuf[WritePos], item->mBonusDexterity); WritePos += PutByte(&SendBuf[WritePos], item->mBonusConstitution); WritePos += PutByte(&SendBuf[WritePos], item->mBonusPsyche); WritePos += PutByte(&SendBuf[WritePos], item->mBonusSpirit); WritePos += PutByte(&SendBuf[WritePos], item->_mBonusHealth); WritePos += PutByte(&SendBuf[WritePos], item->mBonusWill); } else { WritePos += PutInteger(&SendBuf[WritePos], item->mBonusStrength); WritePos += PutInteger(&SendBuf[WritePos], item->mBonusDexterity); WritePos += PutInteger(&SendBuf[WritePos], item->mBonusConstitution); WritePos += PutInteger(&SendBuf[WritePos], item->mBonusPsyche); WritePos += PutInteger(&SendBuf[WritePos], item->mBonusSpirit); if(g_ProtocolVersion < 32) WritePos += PutInteger(&SendBuf[WritePos], item->_mBonusHealth); WritePos += PutInteger(&SendBuf[WritePos], item->mBonusWill); } if(g_ProtocolVersion >= 4) { WritePos += PutByte(&SendBuf[WritePos], item->isCharm); if(item->isCharm != 0) { WritePos += PutFloat(&SendBuf[WritePos], item->mMeleeHitMod); WritePos += PutFloat(&SendBuf[WritePos], item->mMeleeCritMod); WritePos += PutFloat(&SendBuf[WritePos], item->mMagicHitMod); WritePos += PutFloat(&SendBuf[WritePos], item->mMagicCritMod); WritePos += PutFloat(&SendBuf[WritePos], item->mParryMod); WritePos += PutFloat(&SendBuf[WritePos], item->mBlockMod); WritePos += PutFloat(&SendBuf[WritePos], item->mRunSpeedMod); WritePos += PutFloat(&SendBuf[WritePos], item->mRegenHealthMod); WritePos += PutFloat(&SendBuf[WritePos], item->mAttackSpeedMod); WritePos += PutFloat(&SendBuf[WritePos], item->mCastSpeedMod); WritePos += PutFloat(&SendBuf[WritePos], item->mHealingMod); } } if(g_ProtocolVersion >= 5) { WritePos += PutInteger(&SendBuf[WritePos], item->mValue); WritePos += PutByte(&SendBuf[WritePos], item->mValueType); } bool ItemUpdateDefMsgCraft = false; if(g_ProtocolVersion >= 7) ItemUpdateDefMsgCraft = true; if(ItemUpdateDefMsgCraft == true) { WritePos += PutInteger(&SendBuf[WritePos], item->resultItemId); WritePos += PutInteger(&SendBuf[WritePos], item->keyComponentId); WritePos += PutInteger(&SendBuf[WritePos], item->numberOfItems); for(size_t i = 0; i < item->craftItemDefId.size(); i++) WritePos += PutInteger(&SendBuf[WritePos], item->craftItemDefId[i]); if(item->numberOfItems != item->craftItemDefId.size()) g_Logs.server->error("Crafting material item count mismatch for ID: %v", item->mID); } if(g_ProtocolVersion >= 9) WritePos += PutStringUTF(&SendBuf[WritePos], item->mFlavorText.c_str()); if(g_ProtocolVersion >= 18) WritePos += PutByte(&SendBuf[WritePos], item->mSpecialItemType); if(g_ProtocolVersion >= 30) WritePos += PutByte(&SendBuf[WritePos], item->mOwnershipRestriction); if(g_ProtocolVersion >= 31) { WritePos += PutByte(&SendBuf[WritePos], item->mQualityLevel); WritePos += PutShort(&SendBuf[WritePos], item->mMinUseLevel); } PutShort(&SendBuf[1], WritePos - 3); return WritePos; }