diff options
author | David Athay <ko2fan@gmail.com> | 2008-10-31 12:45:17 +0000 |
---|---|---|
committer | David Athay <ko2fan@gmail.com> | 2008-10-31 12:45:17 +0000 |
commit | 3ec0d0f152be4381dc843bc1ca99f8731c8fb366 (patch) | |
tree | 46bba84f40fcffdbede12931bbc92da4f764b4ed /src | |
parent | 8ddad761280216252953bee9467e2787aaee484e (diff) | |
download | manaserv-3ec0d0f152be4381dc843bc1ca99f8731c8fb366.tar.gz manaserv-3ec0d0f152be4381dc843bc1ca99f8731c8fb366.tar.bz2 manaserv-3ec0d0f152be4381dc843bc1ca99f8731c8fb366.tar.xz manaserv-3ec0d0f152be4381dc843bc1ca99f8731c8fb366.zip |
Changed command system to handle commands without template magic.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/game-server/accountconnection.cpp | 33 | ||||
-rw-r--r-- | src/game-server/accountconnection.hpp | 5 | ||||
-rw-r--r-- | src/game-server/commandhandler.cpp | 753 | ||||
-rw-r--r-- | src/game-server/commandhandler.hpp | 71 | ||||
-rw-r--r-- | src/game-server/gamehandler.cpp | 7 | ||||
-rw-r--r-- | src/utils/string.cpp | 13 | ||||
-rw-r--r-- | src/utils/string.hpp | 1 |
8 files changed, 857 insertions, 28 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 5b066875..65e91710 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -95,6 +95,8 @@ tmwserv_game_SOURCES = \ game-server/collisiondetection.hpp \ game-server/collisiondetection.cpp \ game-server/command.cpp \ + game-server/commandhandler.cpp \ + game-server/commandhandler.hpp \ game-server/eventlistener.hpp \ game-server/gamehandler.hpp \ game-server/gamehandler.cpp \ diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp index 159bcb24..492d2a1a 100644 --- a/src/game-server/accountconnection.cpp +++ b/src/game-server/accountconnection.cpp @@ -137,32 +137,7 @@ void AccountConnection::processMessage(MessageIn &msg) { break; } -/* - // create the message - MessageOut out(GPMSG_GET_POST_RESPONSE); - // get all the post for a character - while (msg.getUnreadLength()) - { - // write the sender - out.writeString(msg.readString()); - - // write the contents - out.writeString(msg.readString()); - - // read the number of attachments then - // write the attachments - for (int i = 0; i < msg.readShort(); ++i) - { - // write the id and amount - out.writeShort(msg.readShort()); - out.writeShort(msg.readShort()); - } - } - - // send post to character - gameHandler->sendTo(character, out); - */ std::string sender = msg.readString(); std::string letter = msg.readString(); @@ -302,3 +277,11 @@ void AccountConnection::getPost(Character *c) out.writeLong(c->getDatabaseID()); send(out); } + +void AccountConnection::changeAccountLevel(Character *c, int level) +{ + MessageOut msg(GAMSG_CHANGE_ACCOUNT_LEVEL); + msg.writeLong(c->getDatabaseID()); + msg.writeShort(level); + send(msg); +} diff --git a/src/game-server/accountconnection.hpp b/src/game-server/accountconnection.hpp index 2aa981ea..c722e4d2 100644 --- a/src/game-server/accountconnection.hpp +++ b/src/game-server/accountconnection.hpp @@ -81,6 +81,11 @@ class AccountConnection : public Connection */ void getPost(Character *); + /** + * Change Account Level + */ + void changeAccountLevel(Character *, int); + protected: /** * Processes server messages. diff --git a/src/game-server/commandhandler.cpp b/src/game-server/commandhandler.cpp new file mode 100644 index 00000000..a5be113a --- /dev/null +++ b/src/game-server/commandhandler.cpp @@ -0,0 +1,753 @@ +/* + * The Mana World + * Copyright 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "commandhandler.hpp" +#include "accountconnection.hpp" +#include "character.hpp" +#include "gamehandler.hpp" +#include "inventory.hpp" +#include "item.hpp" +#include "itemmanager.hpp" +#include "mapmanager.hpp" +#include "monster.hpp" +#include "monstermanager.hpp" +#include "state.hpp" + +#include "../utils/string.hpp" + +#include <sstream> + +void CommandHandler::handleCommand(Character *player, + const std::string &command) +{ + // check character permissions + // finer tuning for checking per command can be done + // in the handle function for that command + if (player->getAccountLevel() != AL_GM) + { + return; + } + + // get command type, and arguments + // remove first character (the @) + std::string::size_type pos = command.find(' '); + std::string type(command, 1, pos); + std::string args(command, pos == std::string::npos ? command.size() : pos + 1); + + // handle the command + if (type == "help") + { + handleHelp(player, args); + } + else if (type == "warp") + { + handleWarp(player, args); + } + else if (type == "item") + { + handleItem(player, args); + } + else if (type == "drop") + { + handleDrop(player, args); + } + else if (type == "money") + { + handleMoney(player, args); + } + else if (type == "spawn") + { + handleSpawn(player, args); + } + else if (type == "goto") + { + handleGoto(player, args); + } + else if (type == "recall") + { + handleRecall(player, args); + } + else if (type == "reload") + { + handleReload(player); + } + else if (type == "ban") + { + handleBan(player, args); + } + else if (type == "level") + { + handleLevel(player, args); + } + else if (type == "attribute") + { + handleAttribute(player, args); + } +} + +void CommandHandler::handleHelp(Character *player, std::string &args) +{ + if (args == "") + { + std::stringstream output; + + if (player->getAccountLevel() >= AL_GM) + { + // display GM commands + output << "@help" << std::endl; + output << "@warp" << std::endl; + output << "@item" << std::endl; + output << "@drop" << std::endl; + output << "@money" << std::endl; + output << "@spawn" << std::endl; + output << "@goto" << std::endl; + output << "@recall" << std::endl; + output << "@ban" << std::endl; + output << "@attribute" << std::endl; + } + + if (player->getAccountLevel() == AL_ADMIN) + { + // display Admin commands + output << "@reload" << std::endl; + output << "@level" << std::endl; + } + + GameState::sayTo(player, NULL, output.str()); + } + else + { + + } +} + +void CommandHandler::handleWarp(Character *player, std::string &args) +{ + std::stringstream str; + int x, y; + MapComposite *map; + Character *other; + + // get the arguments + std::string character = getArgument(args); + std::string mapstr = getArgument(args); + std::string xstr = getArgument(args); + std::string ystr = getArgument(args); + + // if any of them are empty strings, no argument was given + if (character == "" || mapstr == "" || xstr == "" || ystr == "") + { + errorMsg("Invalid number of arguments given.", player); + return; + } + + // if it contains # then it means the player + if (character == "#") + { + other = player; + } + else + { + // check for valid player + other = getPlayer(character); + if (!other) + { + errorMsg("Invalid character, or they are offline", player); + return; + } + } + + // if it contains # then it means the player's map + if (mapstr == "#") + { + map = player->getMap(); + } + else + { + // check for valid map id + int id; + if (!utils::isNumeric(mapstr)) + { + errorMsg("Invalid map", player); + return; + } + + str << mapstr; + str >> id; + str.str(""); + + // get the map + map = MapManager::getMap(id); + if (!map) + { + errorMsg("Invalid map", player); + return; + } + } + + if (!utils::isNumeric(xstr)) + { + errorMsg("Invalid x", player); + return; + } + + if (!utils::isNumeric(ystr)) + { + errorMsg("Invalid y", player); + return; + } + + // change the x and y to integers + str << xstr; + str >> x; + str.str(""); + str << ystr; + str >> y; + str.str(""); + + // now warp the player + GameState::warp(other, map, x, y); +} + +void CommandHandler::handleItem(Character *player, std::string &args) +{ + Character *other; + ItemClass *ic; + int value; + int id; + std::stringstream str; + + // get arguments + std::string character = getArgument(args); + std::string itemclass = getArgument(args); + std::string valuestr = getArgument(args); + + // check all arguments are there + if (character == "" || itemclass == "" || valuestr == "") + { + errorMsg("Invalid number of arguments given.", player); + return; + } + + // if it contains # that means the player + if (character == "#") + { + other = player; + } + else + { + // check for valid player + other = getPlayer(character); + if (!other) + { + errorMsg("Invalid character or they are offline", player); + return; + } + } + + // check we have a valid item + if (!utils::isNumeric(itemclass)) + { + errorMsg("Invalid item", player); + return; + } + + // put the itemclass id into an integer + str << itemclass; + str >> id; + str.str(""); + + // check for valid item class + ic = ItemManager::getItem(id); + + if (!ic) + { + errorMsg("Invalid item", player); + return; + } + + if (!utils::isNumeric(valuestr)) + { + errorMsg("Invalid value", player); + return; + } + + str << valuestr; + str >> value; + str.str(""); + + if (value < 0) + { + errorMsg("Invalid amount", player); + return; + } + + // insert the item into the inventory + Inventory(other).insert(ic->getDatabaseID(), value); +} + +void CommandHandler::handleDrop(Character *player, std::string &args) +{ + ItemClass *ic; + int value, id; + std::stringstream str; + + // get arguments + std::string itemclass = getArgument(args); + std::string valuestr = getArgument(args); + + // check all arguments are there + if (itemclass == "" || valuestr == "") + { + errorMsg("Invalid number of arguments given.", player); + return; + } + + // check that itemclass id and value are really integers + if (!utils::isNumeric(itemclass) || !utils::isNumeric(valuestr)) + { + errorMsg("Invalid arguments passed.", player); + return; + } + + // put the item class id into an integer + str << itemclass; + str >> id; + str.str(""); + + // check for valid item + ic = ItemManager::getItem(id); + if (!ic) + { + errorMsg("Invalid item", player); + return; + } + + // put the value into an integer + str << valuestr; + str >> value; + str.str(""); + + if (value < 0) + { + errorMsg("Invalid amount", player); + return; + } + + // create the integer and put it on the map + Item *item = new Item(ic, value); + item->setMap(player->getMap()); + item->setPosition(player->getPosition()); + GameState::insertSafe(item); +} + +void CommandHandler::handleMoney(Character *player, std::string &args) +{ + Character *other; + int value; + std::stringstream str; + + // get arguments + std::string character = getArgument(args); + std::string valuestr = getArgument(args); + + // check all arguments are there + if (character == "" || valuestr == "") + { + errorMsg("Invalid number of arguments given", player); + return; + } + + // check if its the player itself + if (character == "#") + { + other = player; + } + else + { + // check for valid player + other = getPlayer(character); + if (!other) + { + errorMsg("Invalid character or they are offline", player); + return; + } + } + + // check value is an integer + if (!utils::isNumeric(valuestr)) + { + errorMsg("Invalid argument", player); + return; + } + + // change value into an integer + str << valuestr; + str >> value; + str.str(""); + + // change how much money the player has + Inventory(other).changeMoney(value); +} + +void CommandHandler::handleSpawn(Character *player, std::string &args) +{ + MonsterClass *mc; + MapComposite *map = player->getMap(); + Point const &pos = player->getPosition(); + int value, id; + std::stringstream str; + + // get the arguments + std::string monsterclass = getArgument(args); + std::string valuestr = getArgument(args); + + // check all arguments are there + if (monsterclass == "" || valuestr == "") + { + errorMsg("Invalid amount of arguments given.", player); + return; + } + + // check they are really numbers + if (!utils::isNumeric(monsterclass) || !utils::isNumeric(valuestr)) + { + errorMsg("Invalid arguments", player); + return; + } + + // put the monster class id into an integer + str << monsterclass; + str >> id; + str.str(""); + + // check for valid monster + mc = MonsterManager::getMonster(id); + if (!mc) + { + errorMsg("Invalid monster", player); + return; + } + + // put the amount into an integer + str << valuestr; + str >> value; + str.str(""); + + if (value < 0) + { + errorMsg("Invalid amount", player); + return; + } + + // create the monsters and put them on the map + for (int i = 0; i < value; ++i) + { + Being *monster = new Monster(mc); + monster->setMap(map); + monster->setPosition(pos); + monster->clearDestination(); + if (!GameState::insertSafe(monster)) + { + // The map is full. Break out. + break; + } + } +} + +void CommandHandler::handleGoto(Character *player, std::string &args) +{ + Character *other; + + // get the arguments + std::string character = getArgument(args); + + // check all arguments are there + if (character == "") + { + errorMsg("Invalid amount of arguments given.", player); + return; + } + + // check for valid player + other = getPlayer(character); + if (!other) + { + errorMsg("Invalid character, or they are offline.", player); + return; + } + + // move the player to where the other player is + MapComposite *map = other->getMap(); + Point const &pos = other->getPosition(); + GameState::warp(player, map, pos.x, pos.y); +} + +void CommandHandler::handleRecall(Character *player, std::string &args) +{ + Character *other; + + // get the arguments + std::string character = getArgument(args); + + // check all arguments are there + if (character == "") + { + errorMsg("Invalid amount of arguments given.", player); + return; + } + + // check for valid player + other = getPlayer(character); + if (!other) + { + errorMsg("Invalid character, or they are offline.", player); + return; + } + + // move the other player to where the player is + MapComposite *map = player->getMap(); + Point const &pos = player->getPosition(); + GameState::warp(other, map, pos.x, pos.y); +} + +void CommandHandler::handleReload(Character *player) +{ + // check for valid permissions + // reload the items and monsters + if (player->getAccountLevel() == AL_ADMIN) + { + ItemManager::reload(); + MonsterManager::reload(); + } + else + { + errorMsg("Invalid permissions.", player); + } +} + +void CommandHandler::handleBan(Character *player, std::string &args) +{ + Character *other; + int length; + std::stringstream str; + + // get arguments + std::string character = getArgument(args); + std::string valuestr = getArgument(args); + + // check all arguments are there + if (character == "" || valuestr == "") + { + errorMsg("Invalid number of arguments given.", player); + return; + } + + // check for valid player + other = getPlayer(character); + if (!other) + { + errorMsg("Invalid character", player); + return; + } + + // check the length is really an integer + if (!utils::isNumeric(valuestr)) + { + errorMsg("Invalid argument", player); + return; + } + + // change the length to an integer + str << valuestr; + str >> length; + str.str(""); + + if (length < 0) + { + errorMsg("Invalid length", player); + return; + } + + // ban the player + accountHandler->banCharacter(other, length); +} + +void CommandHandler::handleLevel(Character *player, std::string &args) +{ + Character *other; + int level; + std::stringstream str; + + // get the arguments + std::string character = getArgument(args); + std::string valuestr = getArgument(args); + + // check all arguments are there + if (character == "" || valuestr == "") + { + errorMsg("Invalid number of arguments given.", player); + return; + } + + // check if its to effect the player + if (character == "#") + { + other = player; + } + else + { + // check for valid player + other = getPlayer(character); + if (!other) + { + errorMsg("Invalid character", player); + return; + } + } + + // check the amount is really an integer + if (!utils::isNumeric(valuestr)) + { + errorMsg("Invalid argument", player); + return; + } + + // put the amount into an integer + str << valuestr; + str >> level; + str.str(""); + + if (level < 0) + { + errorMsg("Invalid level", player); + return; + } + + // change the player's account level + accountHandler->changeAccountLevel(other, level); +} + +void CommandHandler::handleAttribute(Character *player, std::string &args) +{ + Character *other; + int attr, value; + std::stringstream str; + + // get arguments + std::string character = getArgument(args); + std::string attrstr = getArgument(args); + std::string valuestr = getArgument(args); + + // check all arguments are there + if (character == "" || valuestr == "" || attrstr == "") + { + errorMsg("Invalid number of arguments given.", player); + return; + } + + // check if its the player or another player + if (character == "#") + { + other = player; + } + else + { + // check for valid player + other = getPlayer(character); + if (!other) + { + errorMsg("Invalid character", player); + return; + } + } + + // check they are really integers + if (!utils::isNumeric(valuestr) || !utils::isNumeric(attrstr)) + { + errorMsg("Invalid argument", player); + return; + } + + // put the attribute into an integer + str << attrstr; + str >> attr; + str.str(""); + + if (attr < 0) + { + errorMsg("Invalid Attribute", player); + return; + } + + // put the value into an integer + str << valuestr; + str >> value; + str.str(""); + + if (value < 0) + { + errorMsg("Invalid amount", player); + return; + } + + // change the player's attribute + other->setAttribute(attr, value); +} + +void CommandHandler::errorMsg(const std::string error, Character *player) +{ + // output an error + GameState::sayTo(player, NULL, error); +} + +std::string CommandHandler::getArgument(std::string &args) +{ + std::string argument = ""; + std::string::size_type pos = args.find(' '); + if (pos != std::string::npos) + { + argument = args.substr(0, pos-1); + args = args.substr(pos+1); + } + + return argument; +} + +Character* CommandHandler::getPlayer(const std::string &player) +{ + // get character, via the client, as they may be + // on a different game server + GameClient *client = gameHandler->getClientByNameSlow(player); + if (!client) + { + return NULL; + } + + if (client->status != CLIENT_CONNECTED) + { + return NULL; + } + + return client->character; +} diff --git a/src/game-server/commandhandler.hpp b/src/game-server/commandhandler.hpp new file mode 100644 index 00000000..04df9019 --- /dev/null +++ b/src/game-server/commandhandler.hpp @@ -0,0 +1,71 @@ +/* + * The Mana World + * Copyright 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_SERVER_COMMANDHANDLER_ +#define _TMW_SERVER_COMMANDHANDLER_ + +#include <string> + +class Character; + +/** + * A class to parse and handle user commands + */ +class CommandHandler +{ + public: + /** + * Constructor + */ + CommandHandler() {} + + /** + * Destructor + */ + ~CommandHandler() {} + + /** + * Parse and handle the given command. + */ + void handleCommand(Character *player, const std::string &command); + + private: + void handleHelp(Character *player, std::string &args); + void handleWarp(Character *player, std::string &args); + void handleItem(Character *player, std::string &args); + void handleDrop(Character *player, std::string &args); + void handleMoney(Character *player, std::string &args); + void handleSpawn(Character *player, std::string &args); + void handleGoto(Character *player, std::string &args); + void handleRecall(Character *player, std::string &args); + void handleReload(Character *player); + void handleBan(Character *player, std::string &args); + void handleLevel(Character *player, std::string &args); + void handleAttribute(Character *player, std::string &args); + + void errorMsg(const std::string error, Character *player); + std::string getArgument(std::string &args); + Character* getPlayer(const std::string &player); +}; + +#endif //_TMW_COMMANDHANDLER_H diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index 907bee14..9fd93a46 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -28,6 +28,7 @@ #include "game-server/accountconnection.hpp" #include "game-server/buysell.hpp" +#include "game-server/commandhandler.hpp" #include "game-server/inventory.hpp" #include "game-server/item.hpp" #include "game-server/itemmanager.hpp" @@ -192,9 +193,9 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) if (say[0] == '@') { - // Handle special command. - extern void runCommand(Character *, std::string const &); - runCommand(computer.character, say); + CommandHandler *commandHandler = new CommandHandler(); + commandHandler->handleCommand(computer.character, say); + delete commandHandler; break; } GameState::sayAround(computer.character, say); diff --git a/src/utils/string.cpp b/src/utils/string.cpp index 059903c7..abd6eb88 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -29,3 +29,16 @@ std::string utils::toupper(std::string s) std::transform(s.begin(), s.end(), s.begin(), (int(*)(int)) std::toupper); return s; } + +bool utils::isNumeric(const std::string &s) +{ + for (unsigned int i = 0; i < s.size(); ++i) + { + if (!isdigit(s[i])) + { + return false; + } + } + + return true; +} diff --git a/src/utils/string.hpp b/src/utils/string.hpp index ea70e72a..2adf31b6 100644 --- a/src/utils/string.hpp +++ b/src/utils/string.hpp @@ -27,6 +27,7 @@ namespace utils { std::string toupper(std::string); + bool isNumeric(const std::string &); } #endif // UTILS_STRING_HPP |