//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2003 // // This file is part of Scorched3D. // // Scorched3D 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 // (at your option) any later version. // // Scorched3D 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 Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include ServerTextHandler *ServerTextHandler::instance() { static ServerTextHandler *instance = new ServerTextHandler; return instance; } ServerTextHandler::ServerTextHandler() { ScorchedServer::instance()->getComsMessageHandler().addHandler( "ComsTextMessage", this); } ServerTextHandler::~ServerTextHandler() { } bool ServerTextHandler::processMessage(unsigned int destinationId, const char *messageType, NetBufferReader &reader) { ComsTextMessage message; if (!message.readMessage(reader)) return false; // Check that we don't recieve too much text if (strlen(message.getText()) > 1024) return true; // If the client does not supply a tank id then // get one from the destination unsigned int tankId = message.getPlayerId(); if (tankId == 0) { std::map &tanks = ScorchedServer::instance()->getTankContainer().getAllTanks(); std::map::iterator itor; for (itor = tanks.begin(); itor != tanks.end(); itor++) { Tank *tank = (*itor).second; if (tank->getDestinationId() == destinationId) tankId = tank->getPlayerId(); } } // Check this is a tank, and comes from the correct destination Tank *tank = ScorchedServer::instance()->getTankContainer().getTankById(tankId); if (tank && tank->getDestinationId() == destinationId) { // Construct the message to send to all the clients std::string newText(tank->getName()); if (tank->getState().getMuted()) { newText += " **MUTED**"; } if (tank->getState().getState() != TankState::sNormal) { newText += " ("; newText += tank->getState().getSmallStateString(); newText += ")"; } if (message.getToPlayerId() != 0) { newText += " (Whisper)"; } else if (message.getTeamOnlyMessage()) { newText += " (Team)"; } newText += ": "; unsigned int infoLen = newText.length(); // Filter the string std::string filteredText(message.getText()); ScorchedServerUtil::instance()->textFilter.filterString(filteredText); newText += filteredText; // Remove any bad characters for (char *r = (char *) newText.c_str(); *r; r++) { if (*r == '%') *r = ' '; if (*r < 0) *r = ' '; } const char *sayType = "Says"; if (message.getToPlayerId() != 0) sayType = "Whispers"; else if (message.getTeamOnlyMessage()) sayType = "TeamSays"; // Update the server console with the say text ServerCommon::serverLog(formatString("%s \"%s\"", sayType, newText.c_str())); ComsTextMessage newMessage(newText.c_str(), tank->getPlayerId(), false, message.getTeamOnlyMessage(), infoLen); // Store message addMessage(formatString("%s \"%s\"", sayType, newMessage.getText())); // Send to players if (!tank->getState().getMuted()) { if (message.getToPlayerId() != 0) { // Send all whisper messages to the recipient (or any admins) // Only send to the same destination once std::set doneDests; std::map &tanks = ScorchedServer::instance()->getTankContainer().getPlayingTanks(); std::map::iterator itor; for (itor = tanks.begin(); itor != tanks.end(); itor++) { Tank *currentTank = (*itor).second; if (currentTank->getPlayerId() == message.getToPlayerId() || currentTank->getState().getAdmin()) { if (doneDests.find(currentTank->getDestinationId()) == doneDests.end()) { doneDests.insert(currentTank->getDestinationId()); ComsMessageSender::sendToSingleClient(newMessage, currentTank->getDestinationId()); } } } } else if (message.getTeamOnlyMessage()) { // Send all team messages to everyone in the team (or any admins) // Only send to the same destination once std::set doneDests; std::map &tanks = ScorchedServer::instance()->getTankContainer().getPlayingTanks(); std::map::iterator itor; for (itor = tanks.begin(); itor != tanks.end(); itor++) { Tank *currentTank = (*itor).second; if (tank->getTeam() == currentTank->getTeam() || currentTank->getState().getAdmin()) { if (doneDests.find(currentTank->getDestinationId()) == doneDests.end()) { doneDests.insert(currentTank->getDestinationId()); ComsMessageSender::sendToSingleClient(newMessage, currentTank->getDestinationId()); } } } } else { // Else send to everyone ComsMessageSender::sendToAllConnectedClients(newMessage); } } else { // Only send admin muted texts to the player that said it // and all admins std::map &tanks = ScorchedServer::instance()->getTankContainer().getPlayingTanks(); std::map::iterator itor; for (itor = tanks.begin(); itor != tanks.end(); itor++) { Tank *currentTank = (*itor).second; if (currentTank->getDestinationId() == destinationId || currentTank->getState().getAdmin()) { ComsMessageSender::sendToSingleClient(newMessage, currentTank->getDestinationId()); } } } } return true; } void ServerTextHandler::addMessage(const char *text) { lastMessages_.push_back(text); if (lastMessages_.size() > 25) lastMessages_.pop_front(); }