diff options
author | Erik Schilling <ablu.erikschilling@googlemail.com> | 2012-03-21 21:01:53 +0100 |
---|---|---|
committer | Erik Schilling <ablu.erikschilling@googlemail.com> | 2012-04-19 19:10:50 +0200 |
commit | 67a608b1d13780d19271fedec004bf49b2b2b908 (patch) | |
tree | a5b90dc8f650ebe99185650629bddf3f6c424a19 /src/chat-server | |
parent | a8d65824ea87d5c52ad662530b699650195e83ce (diff) | |
download | manaserv-67a608b1d13780d19271fedec004bf49b2b2b908.tar.gz manaserv-67a608b1d13780d19271fedec004bf49b2b2b908.tar.bz2 manaserv-67a608b1d13780d19271fedec004bf49b2b2b908.tar.xz manaserv-67a608b1d13780d19271fedec004bf49b2b2b908.zip |
Fixed guild support
List of things fixed:
- fixed having multiple guild support everywhere
- implemented kick code (untested due to missing kick possiblity in client)
- fixed giving owner rights to next member when owner leaves guild
- fixed potentional segmention fault when trying to access deleted guild after all members left
- fixed saving right changes to database
- made searching for guilds faster a bit (at least when having many guilds)
TODO:
+ Fix conflict between guild and normal channels
+ Fix being able to leave guild channel without leaving guild itself
+ Add kick possiblity to client
Reviewed-by: bjorn.
Diffstat (limited to 'src/chat-server')
-rw-r--r-- | src/chat-server/chatclient.h | 5 | ||||
-rw-r--r-- | src/chat-server/chathandler.cpp | 3 | ||||
-rw-r--r-- | src/chat-server/chathandler.h | 12 | ||||
-rw-r--r-- | src/chat-server/guild.cpp | 35 | ||||
-rw-r--r-- | src/chat-server/guild.h | 5 | ||||
-rw-r--r-- | src/chat-server/guildhandler.cpp | 237 | ||||
-rw-r--r-- | src/chat-server/guildmanager.cpp | 63 | ||||
-rw-r--r-- | src/chat-server/guildmanager.h | 12 |
8 files changed, 210 insertions, 162 deletions
diff --git a/src/chat-server/chatclient.h b/src/chat-server/chatclient.h index dc077321..a0812a30 100644 --- a/src/chat-server/chatclient.h +++ b/src/chat-server/chatclient.h @@ -47,8 +47,9 @@ class ChatClient : public NetComputer std::string characterName; unsigned int characterId; - std::vector< ChatChannel * > channels; - Party* party; + std::vector<ChatChannel *> channels; + std::vector<Guild *> guilds; + Party *party; unsigned char accountLevel; std::map<ChatChannel*, std::string> userModes; }; diff --git a/src/chat-server/chathandler.cpp b/src/chat-server/chathandler.cpp index 9c74cc30..0446fa30 100644 --- a/src/chat-server/chathandler.cpp +++ b/src/chat-server/chathandler.cpp @@ -127,6 +127,9 @@ void ChatHandler::computerDisconnected(NetComputer *comp) // Remove user from party removeUserFromParty(*computer); + // Notify guilds about him leaving + guildManager->disconnectPlayer(computer); + // Remove the character from the player map // need to do this after removing them from party // as that uses the player map diff --git a/src/chat-server/chathandler.h b/src/chat-server/chathandler.h index af22e453..06d72513 100644 --- a/src/chat-server/chathandler.h +++ b/src/chat-server/chathandler.h @@ -25,7 +25,10 @@ #include <map> #include <string> +#include "chat-server/guild.h" + #include "net/connectionhandler.h" + #include "utils/tokencollector.h" class ChatChannel; @@ -106,7 +109,7 @@ class ChatHandler : public ConnectionHandler /** * Send information about a change in the guild list to guild members. */ - void sendGuildListUpdate(const std::string &guildName, + void sendGuildListUpdate(Guild *guild, const std::string &characterName, char eventId); @@ -182,6 +185,7 @@ class ChatHandler : public ConnectionHandler void handleGuildAcceptInvite(ChatClient &client, MessageIn &msg); void handleGuildGetMembers(ChatClient &client, MessageIn &msg); void handleGuildMemberLevelChange(ChatClient &client, MessageIn &msg); + void removeCharacterFormGuild(ChatClient &client, Guild *guild); void handleGuildKickMember(ChatClient &client, MessageIn &msg); void handleGuildQuit(ChatClient &client, MessageIn &msg); @@ -207,6 +211,12 @@ class ChatHandler : public ConnectionHandler const std::string &text); /** + * Finds out the name of a character by its id. Either searches it + * in the list of online characters or otherwise gets it from the db. + */ + unsigned int getIdOfChar(const std::string &name); + + /** * Sends a message to every client in a registered channel. * * @param channel the channel to send the message in, must not be NULL diff --git a/src/chat-server/guild.cpp b/src/chat-server/guild.cpp index 8ec2c8cc..47ace46e 100644 --- a/src/chat-server/guild.cpp +++ b/src/chat-server/guild.cpp @@ -19,6 +19,9 @@ */ #include "guild.h" + +#include "chat-server/guildmanager.h" + #include "common/defines.h" #include <algorithm> @@ -42,10 +45,7 @@ void Guild::addMember(int playerId, int permissions) // add new guild member to guild mMembers.push_back(member); - if (checkInvited(playerId)) - { - mInvited.remove(playerId); - } + mInvited.remove(playerId); } void Guild::removeMember(int playerId) @@ -53,10 +53,16 @@ void Guild::removeMember(int playerId) if (getOwner() == playerId) { // if the leader is leaving, assign next member as leader - std::list<GuildMember*>::iterator itr = mMembers.begin(); - ++itr; - if (itr != mMembers.end()) - setOwner((*itr)->mId); + for (std::list<GuildMember*>::iterator it = mMembers.begin(), + it_end = mMembers.end(); it != it_end; ++it) + { + GuildMember *member = *it; + if (member->mId != playerId) + { + setOwner(member->mId); + break; + } + } } GuildMember *member = getMember(playerId); if (member) @@ -80,11 +86,7 @@ int Guild::getOwner() const void Guild::setOwner(int playerId) { - GuildMember *member = getMember(playerId); - if (member) - { - member->mPermissions = GAL_OWNER; - } + guildManager->setUserRights(this, playerId, GAL_OWNER); } bool Guild::checkInvited(int playerId) const @@ -97,6 +99,11 @@ void Guild::addInvited(int playerId) mInvited.push_back(playerId); } +void Guild::removeInvited(int playerId) +{ + mInvited.remove(playerId); +} + bool Guild::checkInGuild(int playerId) const { return getMember(playerId) != 0; @@ -129,7 +136,7 @@ bool Guild::canInvite(int playerId) const int Guild::getUserPermissions(int playerId) const { GuildMember *member = getMember(playerId); - return member->mPermissions; + return member ? member->mPermissions : 0; } void Guild::setUserPermissions(int playerId, int level) diff --git a/src/chat-server/guild.h b/src/chat-server/guild.h index 21b1b2e7..9cff757e 100644 --- a/src/chat-server/guild.h +++ b/src/chat-server/guild.h @@ -83,6 +83,11 @@ class Guild void addInvited(int playerId); /** + * Remove a player from the invite list. + */ + void removeInvited(int playerId); + + /** * Returns the name of the guild. */ std::string getName() const diff --git a/src/chat-server/guildhandler.cpp b/src/chat-server/guildhandler.cpp index 110727cf..949728c2 100644 --- a/src/chat-server/guildhandler.cpp +++ b/src/chat-server/guildhandler.cpp @@ -31,6 +31,7 @@ #include "net/messagein.h" #include "net/messageout.h" +#include "common/configuration.h" #include "common/manaserv_protocol.h" using namespace ManaServ; @@ -43,25 +44,31 @@ void ChatHandler::sendGuildInvite(const std::string &invitedName, msg.writeString(inviterName); msg.writeString(guildName); - std::map<std::string, ChatClient*>::iterator itr = mPlayerMap.find(invitedName); - if (itr == mPlayerMap.end()) + ChatClient *client = getClient(invitedName); + if (client) { - itr->second->send(msg); + client->send(msg); } } void ChatHandler::sendGuildRejoin(ChatClient &client) { // Get list of guilds and check what rights they have. - std::vector<Guild*> guilds = guildManager->getGuildsForPlayer(client.characterId); - for (unsigned int i = 0; i != guilds.size(); ++i) + std::vector<Guild *> guilds = + guildManager->getGuildsForPlayer(client.characterId); + + client.guilds = guilds; + + for (std::vector<Guild *>::iterator it = guilds.begin(), + it_end = guilds.end(); it != it_end; ++it) { - const Guild *guild = guilds[i]; + Guild *guild = *it; const int permissions = guild->getUserPermissions(client.characterId); const std::string guildName = guild->getName(); - // Tell the client what guilds the character belongs to and their permissions + // Tell the client what guilds the character belongs to + // and their permissions MessageOut msg(CPMSG_GUILD_REJOIN); msg.writeString(guildName); msg.writeInt16(guild->getId()); @@ -76,7 +83,8 @@ void ChatHandler::sendGuildRejoin(ChatClient &client) client.send(msg); - sendGuildListUpdate(guildName, client.characterName, GUILD_EVENT_ONLINE_PLAYER); + sendGuildListUpdate(guild, client.characterName, + GUILD_EVENT_ONLINE_PLAYER); } } @@ -104,30 +112,26 @@ ChatChannel *ChatHandler::joinGuildChannel(const std::string &guildName, ChatCli return channel; } -void ChatHandler::sendGuildListUpdate(const std::string &guildName, +void ChatHandler::sendGuildListUpdate(Guild *guild, const std::string &characterName, char eventId) { - Guild *guild = guildManager->findByName(guildName); - if (guild) - { - MessageOut msg(CPMSG_GUILD_UPDATE_LIST); + MessageOut msg(CPMSG_GUILD_UPDATE_LIST); - msg.writeInt16(guild->getId()); - msg.writeString(characterName); - msg.writeInt8(eventId); - std::map<std::string, ChatClient*>::const_iterator chr; - std::list<GuildMember*> members = guild->getMembers(); + msg.writeInt16(guild->getId()); + msg.writeString(characterName); + msg.writeInt8(eventId); + std::map<std::string, ChatClient*>::const_iterator chr; + std::list<GuildMember*> members = guild->getMembers(); - for (std::list<GuildMember*>::const_iterator itr = members.begin(); - itr != members.end(); ++itr) + for (std::list<GuildMember*>::const_iterator itr = members.begin(); + itr != members.end(); ++itr) + { + Character *c = storage->getCharacter((*itr)->mId, NULL); + chr = mPlayerMap.find(c->getName()); + if (chr != mPlayerMap.end()) { - Character *c = storage->getCharacter((*itr)->mId, NULL); - chr = mPlayerMap.find(c->getName()); - if (chr != mPlayerMap.end()) - { - chr->second->send(msg); - } + chr->second->send(msg); } } } @@ -140,8 +144,8 @@ void ChatHandler::handleGuildCreate(ChatClient &client, MessageIn &msg) std::string guildName = msg.readString(); if (!guildManager->doesExist(guildName)) { - // check the player hasnt already created a guild - if (guildManager->alreadyOwner(client.characterId)) + if ((int)client.guilds.size() >= + Configuration::getValue("account_maxGuildsPerCharacter", 1)) { reply.writeInt8(ERRMSG_LIMIT_REACHED); } @@ -154,6 +158,8 @@ void ChatHandler::handleGuildCreate(ChatClient &client, MessageIn &msg) reply.writeInt16(guild->getId()); reply.writeInt16(guild->getUserPermissions(client.characterId)); + client.guilds.push_back(guild); + // Send autocreated channel id ChatChannel* channel = joinGuildChannel(guildName, client); reply.writeInt16(channel->getId()); @@ -177,7 +183,7 @@ void ChatHandler::handleGuildInvite(ChatClient &client, MessageIn &msg) std::string character = msg.readString(); // get the chat client and the guild - ChatClient *invitedClient = mPlayerMap[character]; + ChatClient *invitedClient = getClient(character); Guild *guild = guildManager->findById(guildId); if (invitedClient && guild) @@ -185,21 +191,33 @@ void ChatHandler::handleGuildInvite(ChatClient &client, MessageIn &msg) // check permissions of inviter, and that they arent inviting themself, // and arent someone already in the guild if (guild->canInvite(client.characterId) && - (client.characterName != character) && - !guild->checkInGuild(invitedClient->characterId)) + client.characterName != character && + guild->checkInGuild(client.characterId)) { - // send the name of the inviter and the name of the guild - // that the character has been invited to join - std::string senderName = client.characterName; - std::string guildName = guild->getName(); - invite.writeString(senderName); - invite.writeString(guildName); - invite.writeInt16(guildId); - invitedClient->send(invite); - reply.writeInt8(ERRMSG_OK); - - // add member to list of invited members to the guild - guild->addInvited(invitedClient->characterId); + if ((int)invitedClient->guilds.size() >= + Configuration::getValue("account_maxGuildsPerCharacter", 1)) + { + reply.writeInt8(ERRMSG_LIMIT_REACHED); + } + else if (guild->checkInGuild(invitedClient->characterId)) + { + reply.writeInt8(ERRMSG_ALREADY_MEMBER); + } + else + { + // send the name of the inviter and the name of the guild + // that the character has been invited to join + std::string senderName = client.characterName; + std::string guildName = guild->getName(); + invite.writeString(senderName); + invite.writeString(guildName); + invite.writeInt16(guildId); + invitedClient->send(invite); + reply.writeInt8(ERRMSG_OK); + + // add member to list of invited members to the guild + guild->addInvited(invitedClient->characterId); + } } else { @@ -218,37 +236,38 @@ void ChatHandler::handleGuildAcceptInvite(ChatClient &client, MessageIn &msg) { MessageOut reply(CPMSG_GUILD_ACCEPT_RESPONSE); - std::string guildName = msg.readString(); - bool error = true; // set true by default, and set false only if success + const int guildId = msg.readInt16(); + const bool accepted = msg.readInt8(); // check guild exists and that member was invited // then add them as guild member // and remove from invite list - Guild *guild = guildManager->findByName(guildName); - if (guild) + Guild *guild = guildManager->findById(guildId); + if (!(guild && guild->checkInvited(client.characterId))) { - if (guild->checkInvited(client.characterId)) - { - // add user to guild - guildManager->addGuildMember(guild, client.characterId); - reply.writeInt8(ERRMSG_OK); - reply.writeString(guild->getName()); - reply.writeInt16(guild->getId()); - reply.writeInt16(guild->getUserPermissions(client.characterId)); - - // have character join guild channel - ChatChannel *channel = joinGuildChannel(guild->getName(), client); - reply.writeInt16(channel->getId()); - sendGuildListUpdate(guildName, client.characterName, GUILD_EVENT_NEW_PLAYER); - // success! set error to false - error = false; - } + reply.writeInt8(ERRMSG_FAILURE); } - - if (error) + else if (accepted) { - reply.writeInt8(ERRMSG_FAILURE); + // add user to guild + guildManager->addGuildMember(guild, client.characterId); + client.guilds.push_back(guild); + reply.writeInt8(ERRMSG_OK); + reply.writeString(guild->getName()); + reply.writeInt16(guild->getId()); + reply.writeInt16(guild->getUserPermissions(client.characterId)); + + // have character join guild channel + ChatChannel *channel = joinGuildChannel(guild->getName(), client); + reply.writeInt16(channel->getId()); + sendGuildListUpdate(guild, client.characterName, + GUILD_EVENT_NEW_PLAYER); + } + else + { + guild->removeInvited(client.characterId); + reply.writeInt8(ERRMSG_OK); } client.send(reply); @@ -304,7 +323,8 @@ void ChatHandler::handleGuildMemberLevelChange(ChatClient &client, if (guild && c) { int rights = guild->getUserPermissions(c->getDatabaseID()) | level; - if (guildManager->changeMemberLevel(&client, guild, c->getDatabaseID(), rights) == 0) + if (guildManager->changeMemberLevel(&client, guild, c->getDatabaseID(), + rights) == 0) { reply.writeInt8(ERRMSG_OK); client.send(reply); @@ -319,27 +339,50 @@ void ChatHandler::handleGuildKickMember(ChatClient &client, MessageIn &msg) { MessageOut reply(CPMSG_GUILD_KICK_MEMBER_RESPONSE); short guildId = msg.readInt16(); - std::string user = msg.readString(); + std::string otherCharName = msg.readString(); Guild *guild = guildManager->findById(guildId); - Character *c = storage->getCharacter(user); - if (guild && c) + if (!guild) { - if (guild->getUserPermissions(c->getDatabaseID()) & GAL_KICK) - { - reply.writeInt8(ERRMSG_OK); - } - else - { - reply.writeInt8(ERRMSG_INSUFFICIENT_RIGHTS); - } + reply.writeInt8(ERRMSG_INVALID_ARGUMENT); + client.send(reply); + return; } + ChatClient *otherClient = getClient(otherCharName); + unsigned int otherCharId; + if (otherClient) + otherCharId = otherClient->characterId; else + otherCharId = storage->getCharacterId(otherCharName); + + if (otherCharId == 0) { reply.writeInt8(ERRMSG_INVALID_ARGUMENT); + client.send(reply); + return; + } + + if (!((guild->getUserPermissions(client.characterId) & GAL_KICK) && + guild->checkInGuild(otherCharId) && + otherCharId != client.characterId)) + { + reply.writeInt8(ERRMSG_INSUFFICIENT_RIGHTS); + client.send(reply); + return; + } + if (otherClient) + { + // Client is online. Inform him about that he got kicked + MessageOut kickMsg(CPMSG_GUILD_KICK_NOTIFICATION); + kickMsg.writeInt16(guild->getId()); + kickMsg.writeString(client.characterName); + otherClient->send(kickMsg); } + guildManager->removeGuildMember(guild, otherCharId, otherCharName, + otherClient); + reply.writeInt8(ERRMSG_OK); client.send(reply); } @@ -347,40 +390,22 @@ void ChatHandler::handleGuildQuit(ChatClient &client, MessageIn &msg) { MessageOut reply(CPMSG_GUILD_QUIT_RESPONSE); short guildId = msg.readInt16(); - Guild *guild = guildManager->findById(guildId); - // check for valid guild - // check the member is in the guild - // remove the member from the guild - if (guild) - { - if (guild->checkInGuild(client.characterId)) - { - reply.writeInt8(ERRMSG_OK); - reply.writeInt16(guildId); - - // Check if there are no members left, remove the guild channel - if (guild->memberCount() == 0) - { - chatChannelManager->removeChannel(chatChannelManager->getChannelId(guild->getName())); - } - - // guild manager checks if the member is the last in the guild - // and removes the guild if so - guildManager->removeGuildMember(guild, client.characterId); - sendGuildListUpdate(guild->getName(), client.characterName, GUILD_EVENT_LEAVING_PLAYER); - } - else - { - reply.writeInt8(ERRMSG_FAILURE); - } - } - else + Guild *guild = guildManager->findById(guildId); + if (!guild || !guild->checkInGuild(client.characterId)) { reply.writeInt8(ERRMSG_FAILURE); + client.send(reply); + return; } + guildManager->removeGuildMember(guild, client.characterId, + client.characterName, &client); + reply.writeInt8(ERRMSG_OK); + reply.writeInt16(guildId); client.send(reply); + + } void ChatHandler::guildChannelTopicChange(ChatChannel *channel, int playerId, diff --git a/src/chat-server/guildmanager.cpp b/src/chat-server/guildmanager.cpp index 51254862..39b0bdbb 100644 --- a/src/chat-server/guildmanager.cpp +++ b/src/chat-server/guildmanager.cpp @@ -24,6 +24,7 @@ #include "common/manaserv_protocol.h" #include "account-server/storage.h" #include "chat-server/chatclient.h" +#include "chat-server/chatchannelmanager.h" #include "chat-server/chathandler.h" using namespace ManaServ; @@ -49,9 +50,8 @@ Guild* GuildManager::createGuild(const std::string &name, int playerId) // Add guild to db storage->addGuild(guild); - // Add guild, and add owner + // Add guild mGuilds[guild->getId()] = guild; - mOwners.push_back(playerId); // put the owner in the guild addGuildMember(guild, playerId); @@ -67,7 +67,6 @@ Guild* GuildManager::createGuild(const std::string &name, int playerId) void GuildManager::removeGuild(Guild *guild) { storage->removeGuild(guild); - mOwners.remove(guild->getOwner()); mGuilds.erase(guild->getId()); delete guild; } @@ -78,17 +77,37 @@ void GuildManager::addGuildMember(Guild *guild, int playerId) guild->addMember(playerId); } -void GuildManager::removeGuildMember(Guild *guild, int playerId) +void GuildManager::removeGuildMember(Guild *guild, int playerId, + const std::string &characterName, + ChatClient *client) { // remove the user from the guild storage->removeGuildMember(guild->getId(), playerId); guild->removeMember(playerId); + chatHandler->sendGuildListUpdate(guild, characterName, + GUILD_EVENT_LEAVING_PLAYER); + // if theres no more members left delete the guild if (guild->memberCount() == 0) + { + chatChannelManager->removeChannel( + chatChannelManager->getChannelId(guild->getName())); removeGuild(guild); + } - mOwners.remove(playerId); + if (client) + { + for (std::vector<Guild *>::iterator it = client->guilds.begin(), + it_end = client->guilds.end(); it != it_end; ++it) + { + if (*it == guild) + { + client->guilds.erase(it); + break; + } + } + } } Guild *GuildManager::findById(short id) const @@ -115,29 +134,26 @@ bool GuildManager::doesExist(const std::string &name) const return findByName(name) != 0; } -std::vector<Guild*> GuildManager::getGuildsForPlayer(int playerId) const +std::vector<Guild *> GuildManager::getGuildsForPlayer(int playerId) const { - std::vector<Guild*> guildList; - + std::vector<Guild *> guilds; for (std::map<int, Guild*>::const_iterator it = mGuilds.begin(); it != mGuilds.end(); ++it) { if (it->second->checkInGuild(playerId)) { - guildList.push_back(it->second); + guilds.push_back(it->second); } } - return guildList; + return guilds; } void GuildManager::disconnectPlayer(ChatClient *player) { - std::vector<Guild*> guildList = getGuildsForPlayer(player->characterId); - - for (std::vector<Guild*>::const_iterator it = guildList.begin(); - it != guildList.end(); ++it) + for (std::vector<Guild *>::iterator it = player->guilds.begin(), + it_end = player->guilds.end(); it != it_end; ++it) { - chatHandler->sendGuildListUpdate((*it)->getName(), + chatHandler->sendGuildListUpdate(*it, player->characterName, GUILD_EVENT_OFFLINE_PLAYER); } @@ -146,7 +162,7 @@ void GuildManager::disconnectPlayer(ChatClient *player) int GuildManager::changeMemberLevel(ChatClient *player, Guild *guild, int playerId, int level) { - if (guild->checkInGuild(player->characterId) && guild->checkInGuild(playerId)) + if (guild->checkInGuild(playerId)) { int playerLevel = guild->getUserPermissions(player->characterId); @@ -161,21 +177,6 @@ int GuildManager::changeMemberLevel(ChatClient *player, Guild *guild, return -1; } -bool GuildManager::alreadyOwner(int playerId) const -{ - std::list<int>::const_iterator it = mOwners.begin(); - std::list<int>::const_iterator it_end = mOwners.end(); - - while (it != it_end) - { - if (*it == playerId) - return true; - ++it; - } - - return false; -} - void GuildManager::setUserRights(Guild *guild, int playerId, int rights) { // Set and save the member rights diff --git a/src/chat-server/guildmanager.h b/src/chat-server/guildmanager.h index 43085746..06a0e5a4 100644 --- a/src/chat-server/guildmanager.h +++ b/src/chat-server/guildmanager.h @@ -56,7 +56,9 @@ class GuildManager /** * Removes a member from a guild. */ - void removeGuildMember(Guild *guild, int playerId); + void removeGuildMember(Guild *guild, int playerId, + const std::string &characterName, + ChatClient *client = 0); /** * Returns the guild with the given id. O(n) @@ -80,7 +82,7 @@ class GuildManager /** * Return the guilds a character is in */ - std::vector<Guild*> getGuildsForPlayer(int playerId) const; + std::vector<Guild *> getGuildsForPlayer(int playerId) const; /** * Inform guild members that a player has disconnected. @@ -97,18 +99,12 @@ class GuildManager int playerId, int level); /** - * Check if the player already owns a guild - */ - bool alreadyOwner(int playerId) const; - - /** * Set user rights */ void setUserRights(Guild *guild, int playerId, int rights); private: std::map<int, Guild*> mGuilds; - std::list<int> mOwners; }; extern GuildManager *guildManager; |