summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYohann Ferreira <bertram@cegetel.net>2005-12-27 03:42:40 +0000
committerYohann Ferreira <bertram@cegetel.net>2005-12-27 03:42:40 +0000
commit205579c3be58537060785d174f9f67c89444a21b (patch)
tree31c7c8e0af476e70259650e1c577eaf299f3fc78 /src
parentad9ecbf35e0d986d704deba6f8f20ad72a94a99e (diff)
downloadmanaserv-205579c3be58537060785d174f9f67c89444a21b.tar.gz
manaserv-205579c3be58537060785d174f9f67c89444a21b.tar.bz2
manaserv-205579c3be58537060785d174f9f67c89444a21b.tar.xz
manaserv-205579c3be58537060785d174f9f67c89444a21b.zip
Implemented common chat handling, except for chatting in channels. Also the Channel registering/unregistering isn't there yet and the commands needs to be implemented. Added a small slangs filter to reduce bad words in account names and in conversations a little.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/accounthandler.cpp12
-rw-r--r--src/chathandler.cpp175
-rw-r--r--src/chathandler.h34
-rw-r--r--src/connectionhandler.cpp43
-rw-r--r--src/connectionhandler.h19
-rw-r--r--src/defines.h16
-rw-r--r--src/main.cpp52
-rw-r--r--src/utils/slangsfilter.cpp67
-rw-r--r--src/utils/slangsfilter.h43
10 files changed, 427 insertions, 38 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b23ccf37..ad8c046e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,7 +68,9 @@ tmwserv_SOURCES = main.cpp \
utils/cipher.h \
utils/cipher.cpp \
utils/logger.h \
- utils/logger.cpp
+ utils/logger.cpp \
+ utils/slangsfilter.h \
+ utils/slangsfilter.cpp
if BUILD_MYSQL
tmwserv_SOURCES += dal/mysqldataprovider.h \
diff --git a/src/accounthandler.cpp b/src/accounthandler.cpp
index 7441400e..ca65cd1e 100644
--- a/src/accounthandler.cpp
+++ b/src/accounthandler.cpp
@@ -28,7 +28,7 @@
#include "messageout.h"
#include "configuration.h"
#include "utils/logger.h"
-#include <cctype>
+#include "utils/slangsfilter.h"
using tmwserv::Account;
using tmwserv::AccountPtr;
@@ -150,7 +150,15 @@ void AccountHandler::receiveMessage(NetComputer &computer, MessageIn &message)
std::string password = message.readString();
std::string email = message.readString();
- // checking conditions for having a good account.
+ // Checking if the Name is slang's free.
+ if (!tmwserv::utils::filterContent(username))
+ {
+ result.writeShort(SMSG_REGISTER_RESPONSE);
+ result.writeByte(REGISTER_INVALID_USERNAME);
+ LOG_INFO(username << ": has got bad words in it.", 1)
+ break;
+ }
+ // Checking conditions for having a good account.
LOG_INFO(username << " is trying to register.", 1)
bool emailValid = false;
diff --git a/src/chathandler.cpp b/src/chathandler.cpp
index 1a25ce57..73906275 100644
--- a/src/chathandler.cpp
+++ b/src/chathandler.cpp
@@ -21,14 +21,39 @@
* $Id$
*/
+#include <cctype>
#include "chathandler.h"
+#include "state.h"
+#include "being.h"
#include "defines.h"
-#include <iostream>
+#include "utils/logger.h"
+#include "utils/slangsfilter.h"
void ChatHandler::receiveMessage(NetComputer &computer, MessageIn &message)
{
- if (computer.getCharacter().get() == NULL)
- return; // character not selected
+ // If not logged in...
+ if (computer.getAccount().get() == NULL)
+ {
+ LOG_INFO("Not logged in, can't chat...", 2)
+ MessageOut result;
+ result.writeShort(SMSG_CHAT);
+ result.writeByte(CHAT_NOLOGIN);
+ computer.send(result.getPacket());
+ return;
+ }
+ else
+ {
+ // If no character selected yet...
+ if (computer.getCharacter().get() == NULL)
+ {
+ MessageOut result;
+ result.writeShort(SMSG_CHAT);
+ result.writeByte(CHAT_NO_CHARACTER_SELECTED);
+ computer.send(result.getPacket());
+ LOG_INFO("No character selected. Can't chat...", 2)
+ return; // character not selected
+ }
+ }
switch (message.getId())
{
@@ -36,15 +61,55 @@ void ChatHandler::receiveMessage(NetComputer &computer, MessageIn &message)
{
// chat to people around area
std::string text = message.readString();
- short channel = message.readShort();
- std::cout << "Say (" << channel << "): " << text << std::endl;
+ // If it's slang clean,
+ if (tmwserv::utils::filterContent(text))
+ {
+ short channel = message.readShort();
+ LOG_INFO("Say: (Channel " << channel << "): " << text, 2)
+ if ( channel == 0 ) // Let's say that is the default channel for now.
+ {
+ if ( text.substr(0, 1) == "@" || text.substr(0, 1) == "#" || text.substr(0, 1) == "/" )
+ {
+ // The message is a command. Deal with it.
+ handleCommand(computer, text);
+ }
+ else
+ {
+ // The default channel (0) is when the character speaks
+ // to the characters around him in the map.
+ // We, then, look for every characters around him and
+ // send the message to them.
+ // By 'around', let's say 10 tiles square wide for now.
+ sayAround(computer, text);
+ }
+ }
+ else
+ {
+ // We send the message to the players registered in the channel.
+ sayInChannel(computer, channel, text);
+ }
+ }
+ else
+ {
+ warnPlayerAboutBadWords(computer);
+ }
}
break;
case CMSG_ANNOUNCE:
{
std::string text = message.readString();
- std::cout << "Announce: " << text << std::endl;
+ // If it's slang's free.
+ if (tmwserv::utils::filterContent(text))
+ {
+ // We send the message to every players in the default channel
+ // as it is an annouce.
+ announce(computer, text);
+ }
+ else
+ {
+ warnPlayerAboutBadWords(computer);
+ }
}
break;
@@ -52,10 +117,106 @@ void ChatHandler::receiveMessage(NetComputer &computer, MessageIn &message)
{
std::string user = message.readString();
std::string text = message.readString();
+ if (tmwserv::utils::filterContent(text))
+ {
+ // We seek the player to whom the message is told
+ // and send it to her/him.
+ sayToPlayer(computer, user, text);
+ }
+ else
+ {
+ warnPlayerAboutBadWords(computer);
+ }
} break;
default:
- std::cout << "Invalid message type" << std::endl;
+ LOG_INFO("Chat: Invalid message type", 2)
break;
}
}
+
+void ChatHandler::handleCommand(NetComputer &computer, std::string command)
+{
+ LOG_INFO("Chat: Recieved unhandled command: " << command, 2)
+ MessageOut result;
+ result.writeShort(SMSG_CHAT);
+ result.writeShort(0); // The Channel
+ result.writeString("SERVER: Unknown or unhandled command.");
+ computer.send(result.getPacket());
+}
+
+void ChatHandler::warnPlayerAboutBadWords(NetComputer &computer)
+{
+ // We could later count if the player is really often unpolite.
+ MessageOut result;
+ result.writeShort(SMSG_CHAT);
+ result.writeShort(0); // The Channel
+ result.writeString("SERVER: Take care not to use bad words when you speak...");
+ computer.send(result.getPacket());
+
+ LOG_INFO(computer.getCharacter()->getName() << " says bad words.", 2)
+}
+
+void ChatHandler::announce(NetComputer &computer, std::string text)
+{
+ MessageOut result;
+ if ( computer.getAccount()->getLevel() == (AccountLevels)AL_ADMIN ||
+ computer.getAccount()->getLevel() == (AccountLevels)AL_GM )
+ {
+ LOG_INFO("ANNOUNCE: " << text, 0)
+ // Send it to every beings.
+ result.writeShort(SMSG_ANNOUNCEMENT);
+ result.writeString(text);
+ connectionHandler->sendToEveryone(result);
+ }
+ else
+ {
+ result.writeShort(SMSG_SYSTEM);
+ result.writeString("Cannot make announcements. You have not enough rights.");
+ computer.send(result.getPacket());
+ LOG_INFO(computer.getCharacter()->getName() <<
+ " couldn't make an announcement due to insufficient rights.", 2)
+ }
+}
+
+void ChatHandler::sayAround(NetComputer &computer, std::string text)
+{
+ MessageOut result;
+ LOG_INFO( computer.getCharacter()->getName() << " says: " << text, 2)
+ // Send it to every beings around
+ result.writeShort(SMSG_CHAT);
+ result.writeShort(0); // The default channel
+ std::string say = computer.getCharacter()->getName();
+ say += ": ";
+ say += text;
+ result.writeString(say);
+ connectionHandler->sendAround(computer.getCharacter(), result);
+}
+
+void ChatHandler::sayToPlayer(NetComputer &computer, std::string playerName, std::string text)
+{
+ MessageOut result;
+ LOG_INFO( computer.getCharacter()->getName() << " says to " << playerName
+ << ": " << text, 2)
+ // Send it to the being if the being exists
+ result.writeShort(SMSG_PRIVMSG);
+ std::string say = computer.getCharacter()->getName();
+ say += ": ";
+ say += text;
+ result.writeString(say);
+ connectionHandler->sendTo(playerName, result);
+}
+
+void ChatHandler::sayInChannel(NetComputer &computer, short channel, std::string text)
+{
+ MessageOut result;
+ LOG_INFO( computer.getCharacter()->getName() << " says in channel " << channel
+ << ": " << text, 2)
+ // TODO: Send it to every beings in channel
+ result.writeShort(SMSG_CHAT);
+ result.writeShort(channel);
+ std::string say = computer.getCharacter()->getName();
+ say += ": ";
+ say += text;
+ result.writeString(say);
+}
diff --git a/src/chathandler.h b/src/chathandler.h
index 3f9b2307..4c0ebdd6 100644
--- a/src/chathandler.h
+++ b/src/chathandler.h
@@ -38,6 +38,40 @@ class ChatHandler : public MessageHandler
* Receives chat related messages.
*/
void receiveMessage(NetComputer &computer, MessageIn &message);
+
+ private:
+ /**
+ * Deals with command messages
+ */
+ void handleCommand(NetComputer &computer, std::string command);
+
+ /**
+ * Tells the player to be more polite.
+ */
+ void warnPlayerAboutBadWords(NetComputer &computer);
+
+ /**
+ * Announce a message to every being in the default channel.
+ */
+ void announce(NetComputer &computer, std::string text);
+
+ /**
+ * Display a message to every player around one's player
+ * in the default channel.
+ * The tile area has been set to 10 for now.
+ */
+ void sayAround(NetComputer &computer, std::string text);
+
+ /**
+ * Say something private to a player.
+ */
+ void sayToPlayer(NetComputer &computer, std::string playerName, std::string text);
+
+ /**
+ * Say something in a specific channel.
+ */
+ void sayInChannel(NetComputer &computer, short channel, std::string text);
+
};
#endif
diff --git a/src/connectionhandler.cpp b/src/connectionhandler.cpp
index c8ed1c6e..b8172fe0 100644
--- a/src/connectionhandler.cpp
+++ b/src/connectionhandler.cpp
@@ -21,7 +21,6 @@
*/
-#include <iostream>
#include <vector>
#include <sstream>
#include <SDL_net.h>
@@ -256,3 +255,45 @@ void ConnectionHandler::sendTo(tmwserv::BeingPtr beingPtr, MessageOut &msg)
}
}
}
+
+void ConnectionHandler::sendTo(std::string name, MessageOut &msg)
+{
+ for (NetComputers::iterator i = clients.begin();
+ i != clients.end();
+ i++) {
+ if ((*i)->getCharacter().get()->getName() == name) {
+ (*i)->send(msg.getPacket());
+ break;
+ }
+ }
+}
+
+void ConnectionHandler::sendToEveryone(MessageOut &msg)
+{
+ for (NetComputers::iterator i = clients.begin();
+ i != clients.end();
+ i++)
+ {
+ (*i)->send(msg.getPacket());
+ break;
+ }
+}
+
+void ConnectionHandler::sendAround(tmwserv::BeingPtr beingPtr, MessageOut &msg)
+{
+ for (NetComputers::iterator i = clients.begin();
+ i != clients.end();
+ i++) {
+ // See if the other being is near enough, then send the message
+ if (abs((*i)->getCharacter().get()->getX() - beingPtr.get()->getX()) <= AROUND_AREA_IN_TILES )
+ {
+ if (abs((*i)->getCharacter().get()->getY() - beingPtr.get()->getY()) <= AROUND_AREA_IN_TILES )
+ {
+ (*i)->send(msg.getPacket());
+ break;
+ }
+ }
+ }
+}
+
+
diff --git a/src/connectionhandler.h b/src/connectionhandler.h
index 0d3bfa32..54ed6a06 100644
--- a/src/connectionhandler.h
+++ b/src/connectionhandler.h
@@ -104,14 +104,31 @@ class ConnectionHandler
void registerHandler(unsigned int msgId, MessageHandler *handler);
/**
- * Send packet to client with matching Being*
+ * Send packet to client with matching BeingPtr
*/
void sendTo(tmwserv::BeingPtr, MessageOut &);
+ /**
+ * Send packet to client with matching Being name
+ */
+ void sendTo(std::string name, MessageOut &);
+
+ /**
+ * Send packet to every client, used for announcements.
+ */
+ void sendToEveryone(MessageOut &);
+
+ /**
+ * Send packet to every client around the client on screen.
+ */
+ void sendAround(tmwserv::BeingPtr, MessageOut &);
+
private:
std::map<unsigned int, MessageHandler*> handlers;
NetComputers clients;
};
+extern ConnectionHandler *connectionHandler;
+
#endif
diff --git a/src/defines.h b/src/defines.h
index 954380ba..f1b27a27 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -76,7 +76,14 @@ enum {
/**
* Points to give to a brand new character
*/
- POINTS_TO_DISTRIBUTES_AT_LVL1 = 60
+ POINTS_TO_DISTRIBUTES_AT_LVL1 = 60,
+
+ // Screen Related
+/**
+ * Determine the area in which a character
+ * can hear another one speak
+ */
+ AROUND_AREA_IN_TILES = 10
};
/**
@@ -219,6 +226,13 @@ enum {
CHAR_LIST_NOLOGIN
};
+// Chat errors return values
+enum {
+ // CHAT_OK = 0,
+ CHAT_NOLOGIN = 1,
+ CHAT_NO_CHARACTER_SELECTED
+};
+
// Object type enumeration
enum {
OBJECT_ITEM = 0,
diff --git a/src/main.cpp b/src/main.cpp
index 052f86c5..46a87b9b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -90,7 +90,8 @@ ChatHandler *chatHandler = new ChatHandler();
/** Core game message handler */
GameHandler *gameHandler = new GameHandler();
-ConnectionHandler connectionHandler; /**< Primary connection handler */
+/** Primary connection handler */
+ConnectionHandler *connectionHandler = new ConnectionHandler();
/**
* SDL timer callback, sends a <code>TMW_WORLD_TICK</code> event.
@@ -217,6 +218,7 @@ void deinitialize()
delete accountHandler;
delete chatHandler;
delete gameHandler;
+ delete connectionHandler;
// Get rid of persistent data storage
tmwserv::Storage::destroy();
@@ -298,29 +300,29 @@ int main(int argc, char *argv[])
//
// Register message handlers
- connectionHandler.registerHandler(CMSG_LOGIN, accountHandler);
- connectionHandler.registerHandler(CMSG_LOGOUT, accountHandler);
- connectionHandler.registerHandler(CMSG_REGISTER, accountHandler);
- connectionHandler.registerHandler(CMSG_UNREGISTER, accountHandler);
- connectionHandler.registerHandler(CMSG_CHAR_CREATE, accountHandler);
- connectionHandler.registerHandler(CMSG_CHAR_SELECT, accountHandler);
- connectionHandler.registerHandler(CMSG_CHAR_DELETE, accountHandler);
- connectionHandler.registerHandler(CMSG_CHAR_LIST, accountHandler);
-
- connectionHandler.registerHandler(CMSG_SAY, chatHandler);
- connectionHandler.registerHandler(CMSG_ANNOUNCE, chatHandler);
-
- connectionHandler.registerHandler(CMSG_PICKUP, gameHandler);
- connectionHandler.registerHandler(CMSG_USE_OBJECT, gameHandler);
- connectionHandler.registerHandler(CMSG_USE_ITEM, gameHandler); // NOTE: this is probably redundant (CMSG_USE_OBJECT)
- connectionHandler.registerHandler(CMSG_TARGET, gameHandler);
- connectionHandler.registerHandler(CMSG_WALK, gameHandler);
- connectionHandler.registerHandler(CMSG_START_TRADE, gameHandler);
- connectionHandler.registerHandler(CMSG_START_TALK, gameHandler);
- connectionHandler.registerHandler(CMSG_REQ_TRADE, gameHandler);
- connectionHandler.registerHandler(CMSG_EQUIP, gameHandler);
-
- session->startListen(&connectionHandler, SERVER_PORT);
+ connectionHandler->registerHandler(CMSG_LOGIN, accountHandler);
+ connectionHandler->registerHandler(CMSG_LOGOUT, accountHandler);
+ connectionHandler->registerHandler(CMSG_REGISTER, accountHandler);
+ connectionHandler->registerHandler(CMSG_UNREGISTER, accountHandler);
+ connectionHandler->registerHandler(CMSG_CHAR_CREATE, accountHandler);
+ connectionHandler->registerHandler(CMSG_CHAR_SELECT, accountHandler);
+ connectionHandler->registerHandler(CMSG_CHAR_DELETE, accountHandler);
+ connectionHandler->registerHandler(CMSG_CHAR_LIST, accountHandler);
+
+ connectionHandler->registerHandler(CMSG_SAY, chatHandler);
+ connectionHandler->registerHandler(CMSG_ANNOUNCE, chatHandler);
+
+ connectionHandler->registerHandler(CMSG_PICKUP, gameHandler);
+ connectionHandler->registerHandler(CMSG_USE_OBJECT, gameHandler);
+ connectionHandler->registerHandler(CMSG_USE_ITEM, gameHandler); // NOTE: this is probably redundant (CMSG_USE_OBJECT)
+ connectionHandler->registerHandler(CMSG_TARGET, gameHandler);
+ connectionHandler->registerHandler(CMSG_WALK, gameHandler);
+ connectionHandler->registerHandler(CMSG_START_TRADE, gameHandler);
+ connectionHandler->registerHandler(CMSG_START_TALK, gameHandler);
+ connectionHandler->registerHandler(CMSG_REQ_TRADE, gameHandler);
+ connectionHandler->registerHandler(CMSG_EQUIP, gameHandler);
+
+ session->startListen(connectionHandler, SERVER_PORT);
LOG_INFO("Listening on port " << SERVER_PORT << "...", 0)
using namespace tmwserv;
@@ -352,7 +354,7 @@ int main(int argc, char *argv[])
// - Handle all messages that are in the message queue
// - Update all active objects/beings
- state.update(connectionHandler);
+ state.update(*connectionHandler);
}
else if (event.type == SDL_QUIT) {
running = false;
diff --git a/src/utils/slangsfilter.cpp b/src/utils/slangsfilter.cpp
new file mode 100644
index 00000000..e950243b
--- /dev/null
+++ b/src/utils/slangsfilter.cpp
@@ -0,0 +1,67 @@
+/*
+ * The Mana World Server
+ * Copyright 2004 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 "slangsfilter.h"
+
+namespace tmwserv
+{
+namespace utils
+{
+
+/**
+ * The slang table. Don't be surprised. We need to know about bad words in order
+ * to keep them out of the players' conversations.
+*/
+std::string slangs[] = {
+"fuck","shit","slut","whore","bitch",
+"END" // This is the terminator, don't remove it.
+};
+
+bool filterContent(std::string text)
+{
+ bool good = true;
+ unsigned int i = 0;
+ while ( !(slangs[i] == "END") )
+ {
+ for (unsigned int j = 0; j <= text.length(); j++)
+ {
+ // We look for slangs into the sentence.
+ std::string upcasedText = text;
+ std::string upcasedSlang = slangs[i];
+ std::transform(upcasedText.begin(), upcasedText.end(), upcasedText.begin(),
+ (int(*)(int))std::toupper);
+ std::transform(upcasedSlang.begin(), upcasedSlang.end(), upcasedSlang.begin(),
+ (int(*)(int))std::toupper);
+ if ( upcasedText.substr(j, upcasedSlang.length()) == upcasedSlang )
+ {
+ good = false;
+ }
+ }
+ // Next slang
+ i++;
+ }
+
+ return good;
+}
+
+} // ::utils
+} // ::tmwserv
diff --git a/src/utils/slangsfilter.h b/src/utils/slangsfilter.h
new file mode 100644
index 00000000..cb4d2ecc
--- /dev/null
+++ b/src/utils/slangsfilter.h
@@ -0,0 +1,43 @@
+/*
+ * The Mana World Server
+ * Copyright 2004 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 _TMWSERV_SLANGSFILTER_H_
+#define _TMWSERV_SLANGSFILTER_H_
+
+#include <string>
+
+namespace tmwserv
+{
+namespace utils
+{
+
+ /**
+ * Useful to filter slangs automatically, by instance.
+ * @return true if the sentence is slangs clear.
+ */
+ bool filterContent(std::string text);
+
+} // ::utils
+} // ::tmwserv
+
+#endif