ServerHaveModFilesHandler.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <server/ServerHaveModFilesHandler.h>
00022 #include <server/ServerChannelManager.h>
00023 #include <server/ScorchedServer.h>
00024 #include <server/ServerCommon.h>
00025 #include <engine/ModFiles.h>
00026 #include <coms/ComsHaveModFilesMessage.h>
00027 #include <common/OptionsScorched.h>
00028 #include <common/Defines.h>
00029 #include <common/Logger.h>
00030 #include <tank/TankMod.h>
00031 #include <tank/TankContainer.h>
00032 #include <time.h>
00033 
00034 ServerHaveModFilesHandler *ServerHaveModFilesHandler::instance()
00035 {
00036         static ServerHaveModFilesHandler *instance = 
00037                 new ServerHaveModFilesHandler;
00038         return instance;
00039 }
00040 
00041 ServerHaveModFilesHandler::ServerHaveModFilesHandler()
00042 {
00043         ScorchedServer::instance()->getComsMessageHandler().addHandler(
00044                 "ComsHaveModFilesMessage",
00045                 this);
00046 }
00047 
00048 ServerHaveModFilesHandler::~ServerHaveModFilesHandler()
00049 {
00050 }
00051 
00052 bool ServerHaveModFilesHandler::processMessage(
00053         NetMessage &netMessage,
00054         const char *messageType,
00055         NetBufferReader &reader)
00056 {
00057         ComsHaveModFilesMessage message;
00058         if (!message.readMessage(reader)) return false;
00059 
00060         unsigned int destinationId = netMessage.getDestinationId();
00061 
00062         std::list<ModFileEntry *> neededEntries_;
00063         unsigned int neededLength = 0;
00064 
00065         // Build up a list of mod files that this client needs
00066         // and does not already have
00067         {
00068                 std::map<std::string, ModFileEntry *> &modFiles = 
00069                         ScorchedServer::instance()->getModFiles().getFiles();
00070                 std::map<std::string, ModFileEntry *>::iterator itor;
00071                 for (itor = modFiles.begin();
00072                         itor != modFiles.end();
00073                         itor++)
00074                 {
00075                         const std::string &fileName = (*itor).first;
00076                         ModFileEntry *fileEntry = (*itor).second;
00077 
00078                         ModIdentifierEntry *hasEntry = 
00079                                 message.getFile(fileName.c_str());
00080                         if (!hasEntry ||
00081                                 hasEntry->crc != fileEntry->getCompressedCrc() ||
00082                                 hasEntry->length != fileEntry->getCompressedSize())
00083                         {
00084 #ifdef _DEBUG
00085                                 if (!hasEntry)
00086                                 {
00087                                         ServerCommon::serverLog(
00088                                                 S3D::formatStringBuffer("Mod download \"%s\" new file",
00089                                                         fileName.c_str()));
00090                                 }
00091                                 else if (hasEntry->length != fileEntry->getCompressedSize())
00092                                 {
00093                                         ServerCommon::serverLog(
00094                                                 S3D::formatStringBuffer("Mod download \"%s\" size difference %u %u",
00095                                                 fileName.c_str(),
00096                                                 hasEntry->length, 
00097                                                 fileEntry->getCompressedSize()));
00098                                 }
00099                                 else if (hasEntry->crc != fileEntry->getCompressedCrc())
00100                                 {
00101                                         ServerCommon::serverLog(
00102                                                 S3D::formatStringBuffer("Mod download \"%s\" crc difference %u %u",
00103                                                 fileName.c_str(),
00104                                                 hasEntry->crc, 
00105                                                 fileEntry->getCompressedCrc()));
00106                                 }
00107 #endif //_DEBUG
00108 
00109                                 neededEntries_.push_back(fileEntry);
00110                                 neededLength += fileEntry->getCompressedSize();
00111                         }
00112                 }
00113         }
00114 
00115         if (neededEntries_.empty())
00116         {
00117                 // No files need downloading
00118                 ServerChannelManager::instance()->sendText(
00119                         ChannelText("info",
00120                                 "NO_MOD_FILES",
00121                                 "No mod files need downloading"),
00122                         netMessage.getDestinationId(), 
00123                         false);
00124         }
00125 #ifndef S3D_SERVER
00126         else
00127         {
00128                 // Do a sanity check that single player games don't need to download
00129                 // any mod files.  As the server and client is the same process and
00130                 // should be using the same mod directory.
00131                 S3D::dialogExit("ModFiles",
00132                         "ERROR: Single player client required mod files");
00133         }
00134 #else
00135         else if (ScorchedServer::instance()->getOptionsGame().getModDownloadSpeed() == 0)
00136         {
00137                 // If this server does not allow file downloads tell the client
00138                 // and disconnect them
00139                 Logger::log("No mod and mod download disabled");
00140                 ServerChannelManager::instance()->sendText(
00141                         ChannelText("info",
00142                                 "SERVER_REQUIRES_MOD",
00143                                 "This server requires the \"{0}\" Scorched3D mod.\n"
00144                                 "The server does not allow in game file downloads.\n"
00145                                 "You must download and install this mod before you\n"
00146                                 "can connect to this server.",
00147                                 ScorchedServer::instance()->getOptionsGame().getMod()),
00148                         destinationId,
00149                         false);
00150                 ServerCommon::kickDestination(destinationId);
00151         }
00152         else 
00153         {
00154                 int timeLeft = int(
00155                                 float(neededLength) / 
00156                                 float(ScorchedServer::instance()->getOptionsGame().getModDownloadSpeed())
00157                         );
00158                 int timeMinutes = timeLeft / 60;
00159                 int timeSeconds = timeLeft % 60;
00160                 // This server allows file downloads
00161                 // The the client how much needs to be downloaded
00162                 ServerChannelManager::instance()->sendText(
00163                         ChannelText("info",
00164                                 "SERVER_DOWNLOAD_MOD",
00165                                 "This server requires the \"{0}\" Scorched3D mod.\n"
00166                                 "This will require downloading {1} bytes\n"
00167                                 "Maximun {2} bytes per second = Minimum of {3} minutes\n"
00168                                 "Note: This will also depend on how many server\n"
00169                                 "downloads and your link speed.",
00170                                 ScorchedServer::instance()->getOptionsGame().getMod(),
00171                                 neededLength,
00172                                 ScorchedServer::instance()->getOptionsGame().getModDownloadSpeed(),
00173                                 timeMinutes),
00174                         destinationId,
00175                         false);
00176         }
00177 #endif
00178 
00179         // Set the files to download in this tanks profile
00180         std::map<unsigned int, Tank *> &tanks = 
00181                 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00182         std::map<unsigned int, Tank *>::iterator itor;
00183         for (itor = tanks.begin();
00184                 itor != tanks.end();
00185                 itor++)
00186         {
00187                 // For each tank
00188                 Tank *tank = (*itor).second;
00189                 if (netMessage.getDestinationId() == tank->getDestinationId())
00190                 {
00191                         // and for each needed entry
00192                         std::list<ModFileEntry *>::iterator neededItor;
00193                         for (neededItor = neededEntries_.begin();
00194                                 neededItor != neededEntries_.end();
00195                                 neededItor ++)
00196                         {
00197                                 ModFileEntry *entry = (*neededItor);
00198 
00199                                 // Add the entry this tank needs to download
00200                                 ModIdentifierEntry newEntry(entry->getFileName(),
00201                                         0, entry->getCompressedCrc());
00202                                 tank->getMod().addFile(newEntry);
00203                         }
00204                         tank->getMod().setInit(true);
00205                         tank->getMod().setTotalLeft(neededLength);
00206                 }
00207         }
00208 
00209         return true;
00210 }

Generated on Mon Feb 16 15:14:53 2009 for Scorched3D by  doxygen 1.5.3