From f666fd38beefb554d90503811e5a43d504a18345 Mon Sep 17 00:00:00 2001 From: David Athay Date: Tue, 27 Jan 2009 17:14:09 +0000 Subject: Changed guild member permissions. Restricted players to owning only 1 guild. --- src/account-server/dalstorage.cpp | 2 +- src/account-server/dalstorage.hpp | 2 +- src/chat-server/chathandler.cpp | 3 ++ src/chat-server/chathandler.hpp | 5 +++ src/chat-server/guild.cpp | 35 ++++++++++++--------- src/chat-server/guild.hpp | 19 +++--------- src/chat-server/guildhandler.cpp | 65 ++++++++++++++++++++++++++++++--------- src/chat-server/guildmanager.cpp | 54 ++++++++++++++++++++++++++++---- src/chat-server/guildmanager.hpp | 11 +++++++ src/defines.h | 25 +++++++++++++-- 10 files changed, 167 insertions(+), 54 deletions(-) diff --git a/src/account-server/dalstorage.cpp b/src/account-server/dalstorage.cpp index 6547d84a..55a31d30 100644 --- a/src/account-server/dalstorage.cpp +++ b/src/account-server/dalstorage.cpp @@ -996,7 +996,7 @@ void DALStorage::removeGuildMember(int guildId, int memberId) } } -void DALStorage::setMemberRights(int memberId, int rights) +void DALStorage::setMemberRights(int guildId, int memberId, int rights) { std::ostringstream sql; diff --git a/src/account-server/dalstorage.hpp b/src/account-server/dalstorage.hpp index 71c3dfa3..fb8ae138 100644 --- a/src/account-server/dalstorage.hpp +++ b/src/account-server/dalstorage.hpp @@ -250,7 +250,7 @@ class DALStorage * Save guild member rights */ void - setMemberRights(int memberId, int rights); + setMemberRights(int guildId, int memberId, int rights); /** * Get guild list diff --git a/src/chat-server/chathandler.cpp b/src/chat-server/chathandler.cpp index 0fa39400..9240d957 100644 --- a/src/chat-server/chathandler.cpp +++ b/src/chat-server/chathandler.cpp @@ -214,6 +214,9 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) handleGuildMemberLevelChange(computer, message); break; + case PCMSG_GUILD_KICK_MEMBER: + handleGuildMemberKick(computer, message); + case PCMSG_GUILD_QUIT: handleGuildQuit(computer, message); break; diff --git a/src/chat-server/chathandler.hpp b/src/chat-server/chathandler.hpp index efd80320..f1a84484 100644 --- a/src/chat-server/chathandler.hpp +++ b/src/chat-server/chathandler.hpp @@ -233,6 +233,11 @@ class ChatHandler : public ConnectionHandler void handleGuildMemberLevelChange(ChatClient &client, MessageIn &msg); + /** + * Deal with kicking a member + */ + void handleGuildMemberKick(ChatClient &client, MessageIn &msg); + /** * Deal with leaving a guild. */ diff --git a/src/chat-server/guild.cpp b/src/chat-server/guild.cpp index 46fa6cb9..6637ead0 100644 --- a/src/chat-server/guild.cpp +++ b/src/chat-server/guild.cpp @@ -19,6 +19,7 @@ */ #include "guild.hpp" +#include "defines.h" #include @@ -49,39 +50,43 @@ void Guild::addMember(int playerId, int permissions) void Guild::removeMember(int playerId) { - if (checkLeader(playerId)) + if (getOwner() == playerId) { // if the leader is leaving, assign next member as leader std::list::iterator itr = mMembers.begin(); ++itr; if (itr != mMembers.end()) - setLeader((*itr)->mId); + setOwner((*itr)->mId); } GuildMember *member = getMember(playerId); if (member) mMembers.remove(member); } -bool Guild::checkLeader(int playerId) +int Guild::getOwner() { - int leader = 0; - GuildMember *member = getMember(playerId); - // check member exists - if (member) - leader = member->mPermissions; - // check permissions - if (leader == GuildMember::LEADER) - return true; - return false; + std::list::iterator itr = mMembers.begin(); + std::list::iterator itr_end = mMembers.end(); + + while (itr != itr_end) + { + if ((*itr)->mPermissions == GAL_OWNER) + { + return (*itr)->mId; + } + + ++itr; + } + return 0; } -void Guild::setLeader(int playerId) +void Guild::setOwner(int playerId) { GuildMember *member = getMember(playerId); if (member) { - member->mPermissions = GuildMember::LEADER; + member->mPermissions = GAL_OWNER; } } @@ -122,7 +127,7 @@ bool Guild::canInvite(int playerId) // Guild members with permissions above NONE can invite // Check that guild members permissions are not NONE GuildMember *member = getMember(playerId); - if (member->mPermissions > GuildMember::NONE) + if (member->mPermissions & GAL_INVITE) return true; return false; } diff --git a/src/chat-server/guild.hpp b/src/chat-server/guild.hpp index 330c275f..26387382 100644 --- a/src/chat-server/guild.hpp +++ b/src/chat-server/guild.hpp @@ -31,15 +31,6 @@ struct GuildMember { public: - /** - * Permissions - * Members with NONE cannot invite users or set permissions - * Members with COMMANDER can invite other users but - * cannot set permissions - * Members with LEADER can invite users and set permissions - */ - enum { NONE = 0, COMMANDER, LEADER }; - int mId; std::string mName; int mPermissions; @@ -66,7 +57,7 @@ class Guild * Add a member to the guild. * Removes a user from invite list if on it */ - void addMember(int playerId, int permissions = GuildMember::NONE); + void addMember(int playerId, int permissions = 0); /** * Remove a member from the guild. @@ -74,14 +65,14 @@ class Guild void removeMember(int playerId); /** - * Check player is the leader of the guild. + * Return owner id */ - bool checkLeader(int playerId); + int getOwner(); /** - * Set player as leader of the guild. + * Set player as owner of the guild. */ - void setLeader(int playerId); + void setOwner(int playerId); /** * Set the ID of the guild. diff --git a/src/chat-server/guildhandler.cpp b/src/chat-server/guildhandler.cpp index 8873988d..9d2c159e 100644 --- a/src/chat-server/guildhandler.cpp +++ b/src/chat-server/guildhandler.cpp @@ -146,16 +146,24 @@ ChatHandler::handleGuildCreation(ChatClient &client, MessageIn &msg) std::string guildName = msg.readString(); if (!guildManager->doesExist(guildName)) { - // Guild doesnt already exist so create it - Guild *guild = guildManager->createGuild(guildName, client.characterId); - reply.writeByte(ERRMSG_OK); - reply.writeString(guildName); - reply.writeShort(guild->getId()); - reply.writeShort(guild->getUserPermissions(client.characterId)); - - // Send autocreated channel id - ChatChannel* channel = joinGuildChannel(guildName, client); - reply.writeShort(channel->getId()); + // check the player hasnt already created a guild + if (guildManager->alreadyOwner(client.characterId)) + { + reply.writeByte(ERRMSG_LIMIT_REACHED); + } + else + { + // Guild doesnt already exist so create it + Guild *guild = guildManager->createGuild(guildName, client.characterId); + reply.writeByte(ERRMSG_OK); + reply.writeString(guildName); + reply.writeShort(guild->getId()); + reply.writeShort(guild->getUserPermissions(client.characterId)); + + // Send autocreated channel id + ChatChannel* channel = joinGuildChannel(guildName, client); + reply.writeShort(channel->getId()); + } } else { @@ -303,7 +311,8 @@ ChatHandler::handleGuildMemberLevelChange(ChatClient &client, MessageIn &msg) if (guild && c) { - if (guildManager->changeMemberLevel(&client, guild, c->getDatabaseID(), level) == 0) + int rights = guild->getUserPermissions(c->getDatabaseID()) | level; + if (guildManager->changeMemberLevel(&client, guild, c->getDatabaseID(), rights) == 0) { reply.writeByte(ERRMSG_OK); client.send(reply); @@ -314,6 +323,34 @@ ChatHandler::handleGuildMemberLevelChange(ChatClient &client, MessageIn &msg) client.send(reply); } +void ChatHandler::handleGuildMemberKick(ChatClient &client, MessageIn &msg) +{ + MessageOut reply(CPMSG_GUILD_KICK_MEMBER_RESPONSE); + short guildId = msg.readShort(); + std::string user = msg.readString(); + + Guild *guild = guildManager->findById(guildId); + Character *c = storage->getCharacter(user); + + if (guild && c) + { + if (guild->getUserPermissions(c->getDatabaseID()) & GAL_KICK) + { + reply.writeByte(ERRMSG_OK); + } + else + { + reply.writeByte(ERRMSG_INSUFFICIENT_RIGHTS); + } + } + else + { + reply.writeByte(ERRMSG_INVALID_ARGUMENT); + } + + client.send(reply); +} + void ChatHandler::handleGuildQuit(ChatClient &client, MessageIn &msg) { @@ -331,8 +368,8 @@ ChatHandler::handleGuildQuit(ChatClient &client, MessageIn &msg) reply.writeByte(ERRMSG_OK); reply.writeShort(guildId); - // Check if they are the leader, and if so, remove the guild channel - if (guild->checkLeader(client.characterId)) + // Check if there are no members left, remove the guild channel + if (guild->totalMembers() == 0) { chatChannelManager->removeChannel(chatChannelManager->getChannelId(guild->getName())); } @@ -361,7 +398,7 @@ ChatHandler::guildChannelTopicChange(ChatChannel *channel, int playerId, const s Guild *guild = guildManager->findByName(channel->getName()); if (guild) { - if(guild->checkLeader(playerId)) + if(guild->getUserPermissions(playerId) & GAL_TOPIC_CHANGE) { chatChannelManager->setChannelTopic(channel->getId(), topic); } diff --git a/src/chat-server/guildmanager.cpp b/src/chat-server/guildmanager.cpp index 1a61588c..cf4ceef6 100644 --- a/src/chat-server/guildmanager.cpp +++ b/src/chat-server/guildmanager.cpp @@ -47,15 +47,17 @@ Guild* GuildManager::createGuild(const std::string &name, int playerId) // Add guild to db storage->addGuild(guild); - // Make sure to add guild to mGuilds before searching for it to add the - // player + // Add guild, and add owner mGuilds.push_back(guild); + mOwners.push_back(playerId); + + // put the owner in the guild addGuildMember(guild, playerId); // Set and save the member rights - storage->setMemberRights(playerId, GuildMember::LEADER); + storage->setMemberRights(guild->getId(), playerId, GAL_OWNER); - guild->setLeader(playerId); + guild->setOwner(playerId); return guild; } @@ -65,6 +67,7 @@ void GuildManager::removeGuild(Guild *guild) if (!guild) return; storage->removeGuild(guild); + mOwners.remove(guild->getOwner()); mGuilds.remove(guild); delete guild; } @@ -81,12 +84,27 @@ void GuildManager::removeGuildMember(Guild *guild, int playerId) { if (!guild) return; + + // remove the user from the guild storage->removeGuildMember(guild->getId(), playerId); guild->removeMember(playerId); + + // if theres no more members left delete the guild if(guild->totalMembers() == 0) { removeGuild(guild); } + + // remove the user from owners list + std::list::iterator itr = mOwners.begin(); + std::list::iterator itr_end = mOwners.end(); + while (itr != itr_end) + { + if ((*itr) == playerId) + mOwners.remove(playerId); + + ++itr; + } } Guild *GuildManager::findById(short id) @@ -161,10 +179,10 @@ int GuildManager::changeMemberLevel(ChatClient *player, Guild *guild, { int playerLevel = guild->getUserPermissions(player->characterId); - if (playerLevel == GuildMember::LEADER) + if (playerLevel == GAL_OWNER) { // player can modify anyones permissions - guild->setUserPermissions(playerId, level); + setUserRights(guild, playerId, level); return 0; } } @@ -172,3 +190,27 @@ int GuildManager::changeMemberLevel(ChatClient *player, Guild *guild, return -1; } +bool GuildManager::alreadyOwner(int playerId) +{ + std::list::iterator itr = mOwners.begin(); + std::list::iterator itr_end = mOwners.end(); + + for (itr; itr != itr_end; ++itr) + { + if ((*itr) == playerId) + { + return true; + } + } + + return false; +} + +void GuildManager::setUserRights(Guild *guild, int playerId, int rights) +{ + // Set and save the member rights + storage->setMemberRights(guild->getId(), playerId, rights); + + // Set with guild + guild->setUserPermissions(playerId, rights); +} diff --git a/src/chat-server/guildmanager.hpp b/src/chat-server/guildmanager.hpp index 1471fe8e..0fb51460 100644 --- a/src/chat-server/guildmanager.hpp +++ b/src/chat-server/guildmanager.hpp @@ -106,8 +106,19 @@ class GuildManager int changeMemberLevel(ChatClient *player, Guild *guild, int playerId, int level); + /** + * Check if the player already owns a guild + */ + bool alreadyOwner(int playerId); + + /** + * Set user rights + */ + void setUserRights(Guild *guild, int playerId, int rights); + private: std::list mGuilds; + std::list mOwners; }; extern GuildManager *guildManager; diff --git a/src/defines.h b/src/defines.h index b722e0d1..e9f5b7b8 100644 --- a/src/defines.h +++ b/src/defines.h @@ -39,6 +39,23 @@ enum AL_ADMIN = 128 /**< User can perform administrator tasks. */ }; +/** + * Guild member permissions + * Members with NONE cannot invite users or set permissions + * Members with TOPIC_CHANGE can change the guild channel topic + * Members with INVIT can invite other users + * Memeber with KICK can remove other users + * Members with OWNER can invite users and set permissions + */ +enum +{ + GAL_NONE = 0, + GAL_TOPIC_CHANGE = 1, + GAL_INVITE = 2, + GAL_KICK = 4, + GAL_OWNER = 255 +}; + enum { // Network related @@ -223,9 +240,11 @@ enum { CPMSG_GUILD_QUIT_RESPONSE = 0x0361, // B error PCMSG_GUILD_PROMOTE_MEMBER = 0x0365, // W guild, S name, B rights CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE = 0x0366, // B error + PCMSG_GUILD_KICK_MEMBER = 0x0370, // W guild, S name + CPMSG_GUILD_KICK_MEMBER_RESPONSE = 0x0371, // B error - CPMSG_GUILD_INVITED = 0x0370, // S char name, S guild name, W id - CPMSG_GUILD_REJOIN = 0x0371, // S name, W guild, W rights, W channel, S announce + CPMSG_GUILD_INVITED = 0x0388, // S char name, S guild name, W id + CPMSG_GUILD_REJOIN = 0x0389, // S name, W guild, W rights, W channel, S announce // Party PCMSG_PARTY_INVITE = 0x03A0, // S name @@ -300,7 +319,7 @@ enum { ERRMSG_ALREADY_TAKEN, // name used was already taken ERRMSG_SERVER_FULL, // the server is overloaded ERRMSG_TIME_OUT, // data failed to arrive in due time - ERRMSG_TOO_MANY_ATTACHMENTS // too many attachments in letter + ERRMSG_LIMIT_REACHED // limit reached }; // used in AGMSG_REGISTER_RESPONSE to show state of item db -- cgit v1.2.3-60-g2f50 From 2141fae61af1fd3f81d792910ffa35d672835523 Mon Sep 17 00:00:00 2001 From: David Athay Date: Wed, 28 Jan 2009 14:24:22 +0000 Subject: Moved MapContent into header file. --- gameserver.cbp | 4 ++ src/game-server/mapcomposite.cpp | 142 +++++++-------------------------------- src/game-server/mapcomposite.hpp | 97 ++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 118 deletions(-) diff --git a/gameserver.cbp b/gameserver.cbp index 64bfb8a1..a2de9765 100644 --- a/gameserver.cbp +++ b/gameserver.cbp @@ -130,6 +130,10 @@ + + + + diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index 333d5ae7..b9e4b863 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -43,104 +43,6 @@ in dealing with zone changes. */ static int const zoneDiam = 256; -/** - * Part of a map. - */ -struct MapZone -{ - unsigned short nbCharacters, nbMovingObjects; - /** - * Objects present in this zone. - * Characters are stored first, then the remaining MovingObjects, then the - * remaining Objects. - */ - std::vector< Object * > objects; - - /** - * Destinations of the objects that left this zone. - * This is necessary in order to have an accurate iterator around moving - * objects. - */ - MapRegion destinations; - - MapZone(): nbCharacters(0), nbMovingObjects(0) {} - void insert(Object *); - void remove(Object *); -}; - -/** - * Pool of public IDs for MovingObjects on a map. By maintaining public ID - * availability using bits, it can locate an available public ID fast while - * using minimal memory access. - */ -struct ObjectBucket -{ - static int const int_bitsize = sizeof(unsigned) * 8; - unsigned bitmap[256 / int_bitsize]; /**< Bitmap of free locations. */ - short free; /**< Number of empty places. */ - short next_object; /**< Next object to look at. */ - MovingObject *objects[256]; - - ObjectBucket(); - int allocate(); - void deallocate(int); -}; - -/** - * Entities on a map. - */ -struct MapContent -{ - MapContent(Map *); - ~MapContent(); - - /** - * Allocates a unique ID for a moving object on this map. - */ - bool allocate(MovingObject *); - - /** - * Deallocates an ID. - */ - void deallocate(MovingObject *); - - /** - * Fills a region of zones within the range of a point. - */ - void fillRegion(MapRegion &, Point const &, int) const; - - /** - * Fills a region of zones inside a rectangle. - */ - void fillRegion(MapRegion &, Rectangle const &) const; - - /** - * Gets zone at given position. - */ - MapZone &getZone(Point const &pos) const - { return zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth]; } - - /** - * Things (items, characters, monsters, etc) located on the map. - */ - std::vector< Thing * > things; - - /** - * Buckets of MovingObjects located on the map, referenced by ID. - */ - ObjectBucket *buckets[256]; - - int last_bucket; /**< Last bucket acted upon. */ - - /** - * Partition of the Objects, depending on their position on the map. - */ - MapZone *zones; - - unsigned short mapWidth; /**< Width with respect to zones. */ - unsigned short mapHeight; /**< Height with respect to zones. */ -}; - void MapZone::insert(Object *obj) { int type = obj->getType(); @@ -443,26 +345,6 @@ MapContent::~MapContent() delete[] zones; } -void MapComposite::setMap(Map *m) -{ - assert(!mMap && m); - mMap = m; - mContent = new MapContent(m); -} - - -MapComposite::MapComposite(int id, std::string const &name): - mMap(NULL), mContent(NULL), mScript(NULL), mName(name), mID(id) -{ -} - -MapComposite::~MapComposite() -{ - delete mMap; - delete mContent; - delete mScript; -} - bool MapContent::allocate(MovingObject *obj) { // First, try allocating from the last used bucket. @@ -538,6 +420,23 @@ void MapContent::fillRegion(MapRegion &r, Rectangle const &p) const } } +MapZone& MapContent::getZone(Point const &pos) const +{ + return zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth]; +} + +MapComposite::MapComposite(int id, std::string const &name): + mMap(NULL), mContent(NULL), mScript(NULL), mName(name), mID(id) +{ +} + +MapComposite::~MapComposite() +{ + delete mMap; + delete mContent; + delete mScript; +} + ZoneIterator MapComposite::getAroundPointIterator(Point const &p, int radius) const { MapRegion r; @@ -628,6 +527,13 @@ void MapComposite::remove(Thing *ptr) assert(false); } +void MapComposite::setMap(Map *m) +{ + assert(!mMap && m); + mMap = m; + mContent = new MapContent(m); +} + void MapComposite::update() { for (int i = 0; i < mContent->mapHeight * mContent->mapWidth; ++i) diff --git a/src/game-server/mapcomposite.hpp b/src/game-server/mapcomposite.hpp index 3f1225f0..078842d6 100644 --- a/src/game-server/mapcomposite.hpp +++ b/src/game-server/mapcomposite.hpp @@ -119,6 +119,103 @@ struct ObjectIterator operator bool() const { return iterator; } }; +/** + * Part of a map. + */ +struct MapZone +{ + unsigned short nbCharacters, nbMovingObjects; + /** + * Objects present in this zone. + * Characters are stored first, then the remaining MovingObjects, then the + * remaining Objects. + */ + std::vector< Object * > objects; + + /** + * Destinations of the objects that left this zone. + * This is necessary in order to have an accurate iterator around moving + * objects. + */ + MapRegion destinations; + + MapZone(): nbCharacters(0), nbMovingObjects(0) {} + void insert(Object *); + void remove(Object *); +}; + +/** + * Pool of public IDs for MovingObjects on a map. By maintaining public ID + * availability using bits, it can locate an available public ID fast while + * using minimal memory access. + */ +struct ObjectBucket +{ + static int const int_bitsize = sizeof(unsigned) * 8; + unsigned bitmap[256 / int_bitsize]; /**< Bitmap of free locations. */ + short free; /**< Number of empty places. */ + short next_object; /**< Next object to look at. */ + MovingObject *objects[256]; + + ObjectBucket(); + int allocate(); + void deallocate(int); +}; + +/** + * Entities on a map. + */ +struct MapContent +{ + MapContent(Map *); + ~MapContent(); + + /** + * Allocates a unique ID for a moving object on this map. + */ + bool allocate(MovingObject *); + + /** + * Deallocates an ID. + */ + void deallocate(MovingObject *); + + /** + * Fills a region of zones within the range of a point. + */ + void fillRegion(MapRegion &, Point const &, int) const; + + /** + * Fills a region of zones inside a rectangle. + */ + void fillRegion(MapRegion &, Rectangle const &) const; + + /** + * Gets zone at given position. + */ + MapZone &getZone(Point const &pos) const; + + /** + * Things (items, characters, monsters, etc) located on the map. + */ + std::vector< Thing * > things; + + /** + * Buckets of MovingObjects located on the map, referenced by ID. + */ + ObjectBucket *buckets[256]; + + int last_bucket; /**< Last bucket acted upon. */ + + /** + * Partition of the Objects, depending on their position on the map. + */ + MapZone *zones; + + unsigned short mapWidth; /**< Width with respect to zones. */ + unsigned short mapHeight; /**< Height with respect to zones. */ +}; + /** * Combined map/entity structure. */ -- cgit v1.2.3-60-g2f50