ClientNewGameHandler.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 <client/ScorchedClient.h>
00022 #include <client/ClientNewGameHandler.h>
00023 #include <client/ClientState.h>
00024 #include <client/ClientWaitState.h>
00025 #include <client/ClientReloadAdaptor.h>
00026 #include <graph/SpeedChange.h>
00027 #include <graph/OptionsDisplayConsole.h>
00028 #include <graph/MainCamera.h>
00029 #include <tankgraph/RenderTracer.h>
00030 #include <weapons/AccessoryStore.h>
00031 #include <engine/ActionController.h>
00032 #include <engine/MainLoop.h>
00033 #include <GLW/GLWWindowManager.h>
00034 #include <client/ClientParams.h>
00035 #include <common/OptionsScorched.h>
00036 #include <common/ChannelManager.h>
00037 #include <common/Clock.h>
00038 #include <common/Logger.h>
00039 #include <coms/ComsNewGameMessage.h>
00040 #include <dialogs/PlayerDialog.h>
00041 #include <dialogs/ProgressDialog.h>
00042 #include <dialogs/RulesDialog.h>
00043 #include <landscapemap/LandscapeMaps.h>
00044 #include <landscapemap/DeformLandscape.h>
00045 #include <landscapedef/LandscapeDefinitions.h>
00046 #include <landscape/Landscape.h>
00047 #include <tank/TankContainer.h>
00048 #include <tank/TankCamera.h>
00049 #include <target/TargetRenderer.h>
00050 #include <tankai/TankAIAdder.h>
00051 
00052 ClientNewGameHandler *ClientNewGameHandler::instance_ = 0;
00053 
00054 ClientNewGameHandler *ClientNewGameHandler::instance()
00055 {
00056         if (!instance_)
00057         {
00058           instance_ = new ClientNewGameHandler();
00059         }
00060 
00061         return instance_;
00062 }
00063 
00064 ClientNewGameHandler::ClientNewGameHandler()
00065 {
00066         ScorchedClient::instance()->getComsMessageHandler().addHandler(
00067                 "ComsNewGameMessage",
00068                 this);
00069 }
00070 
00071 ClientNewGameHandler::~ClientNewGameHandler()
00072 {
00073 
00074 }
00075 
00076 bool ClientNewGameHandler::processMessage(
00077         NetMessage &netMessage,
00078         const char *messageType,
00079         NetBufferReader &reader)
00080 {
00081         Clock generateClock;
00082         bool result = actualProcessMessage(netMessage, messageType, reader);
00083         float generateTime = generateClock.getTimeDifference();
00084         int idleTime = ScorchedClient::instance()->getOptionsGame().getIdleKickTime();
00085 
00086         if (idleTime > 0 && int(generateTime) > idleTime - 5)
00087         {
00088                 LangString message = LANG_RESOURCE("LEVEL_TIMEOUT_WARNING",
00089                         "Warning: Your PC is taking a long time to generate levels.\n"
00090                         "This may cause you to be kicked by some servers.\n"
00091                         "You can fix this by lowering your display settings");
00092 
00093                 Logger::log(LangStringUtil::convertFromLang(message));
00094                 ChannelText text("info", message);
00095                 ChannelManager::showText(ScorchedClient::instance()->getContext(), text);
00096         }
00097 
00098         return result;
00099 }
00100 
00101 bool ClientNewGameHandler::actualProcessMessage(
00102         NetMessage &netMessage,
00103         const char *messageType,
00104         NetBufferReader &reader)
00105 {
00106         ComsNewGameMessage message;
00107         if (!message.readMessage(reader)) return false;
00108 
00109         // Update all of the tank state
00110         // Do this at the begining as the ProgressDialog processes network
00111         // events and tanks may leave an join meantime
00112         if (!message.parsePlayerStateMessage())
00113         {
00114                 Logger::log("ClientNewGameHandler: Failed to parse playerstate");
00115                 return false;
00116         }
00117 
00118         // make sure we can only see the correct settings
00119         OptionsDisplayConsole::instance()->addDisplayToConsole();
00120 
00121         // Set the progress dialog nicities
00122         ProgressDialog::instance()->changeTip();
00123         LandscapeDefinitionsEntry *landscapeDefinition =
00124                 ScorchedClient::instance()->getLandscapes().getLandscapeByName(
00125                         message.getLevelMessage().getGroundMapsDefn().getName());
00126         if (landscapeDefinition)
00127         {
00128                 std::string fileName = S3D::getDataFile(
00129                         S3D::formatStringBuffer("data/landscapes/%s", 
00130                         landscapeDefinition->picture.c_str()));
00131                 ProgressDialog::instance()->setIcon(fileName.c_str());
00132         }
00133 
00134         // Remove any old targets
00135         removeTargets();
00136 
00137         // Generate new landscape
00138         ScorchedClient::instance()->getLandscapeMaps().generateMaps(
00139                 ScorchedClient::instance()->getContext(),
00140                 message.getLevelMessage().getGroundMapsDefn(),
00141                 ProgressDialogSync::instance());
00142 
00143         Clock generateClock;
00144         DeformLandscape::applyInfos(
00145                 ScorchedClient::instance()->getContext(),
00146                 message.getLevelMessage().getDeformInfos(),
00147                 ProgressDialogSync::instance());
00148         float deformTime = generateClock.getTimeDifference();
00149         Logger::log(S3D::formatStringBuffer("Landscape deformation time %.2f seconds", deformTime));
00150 
00151         // Calculate all the new landscape settings (graphics)
00152         Landscape::instance()->generate(ProgressDialogSync::instance());
00153 
00154         // Remove any targets that have been removed due to game play
00155         std::map<unsigned int, Target *> targets =
00156                 ScorchedClient::instance()->getTargetContainer().getTargets(); // Copy
00157         std::map<unsigned int, Target *>::iterator targetItor;
00158         for (targetItor = targets.begin();
00159                 targetItor != targets.end();
00160                 targetItor++)
00161         {
00162                 Target *target = targetItor->second;
00163                 if (target->getPlayerId() >= TargetID::MIN_TARGET_ID &&
00164                         target->getPlayerId() < TargetID::MIN_TARGET_TRANSIENT_ID)
00165                 {
00166                         if (message.getLevelMessage().getTargetIds().find(target->getPlayerId()) ==
00167                                 message.getLevelMessage().getTargetIds().end())
00168                         {
00169                                 if (target->isTarget())
00170                                 {
00171                                         Target *removedTarget = 
00172                                                 ScorchedClient::instance()->getTargetContainer().removeTarget(target->getPlayerId());
00173                                         delete removedTarget;
00174                                 }
00175                                 else
00176                                 {
00177                                         // Should never happen as tanks (even temporary ones) aren't removed
00178                                         // from the container set when killed
00179                                         Tank *removedTank = 
00180                                                 ScorchedClient::instance()->getTankContainer().removeTank(target->getPlayerId());
00181                                         delete removedTank;
00182                                 }
00183                         }
00184                 }
00185         }
00186 
00187         // Add any targets that have been added due to game play
00188         NetBufferReader newTargets(message.getLevelMessage().getNewTargets());
00189         unsigned int newTargetId = 0;
00190         while (newTargets.getFromBuffer(newTargetId))
00191         {
00192                 Target *newTarget = new Target(
00193                         newTargetId, 
00194                         LangString(), 
00195                         ScorchedClient::instance()->getContext());
00196                 if (!newTarget->readMessage(newTargets))
00197                 {
00198                         Logger::log("ClientNewGameHandler: Failed to parse new target message");
00199                         return false;
00200                 }
00201 
00202                 ScorchedClient::instance()->getTargetContainer().addTarget(newTarget);
00203         }
00204 
00205         // Change any target values that may have been altered
00206         NetBufferReader oldTargets(message.getLevelMessage().getOldTargets());
00207         unsigned int oldTargetId = 0;
00208         while (oldTargets.getFromBuffer(oldTargetId))
00209         {
00210                 Target *oldTarget = ScorchedClient::instance()->
00211                         getTargetContainer().getTargetById(oldTargetId);
00212                 if (!oldTarget)
00213                 {
00214                         Logger::log("ClientNewGameHandler: Failed to find old target");
00215                         return false;
00216                 }
00217 
00218                 if (!oldTarget->readMessage(oldTargets))
00219                 {
00220                         Logger::log("ClientNewGameHandler: Failed to parse old target message");
00221                         return false;
00222                 }
00223         }
00224 
00225         // Make sure the landscape has been optimized
00226         Landscape::instance()->reset(ProgressDialogSync::instance());
00227 
00228         RenderTracer::instance()->newGame();
00229         SpeedChange::instance()->resetSpeed();
00230 
00231         // Remove all actions (graphical objects) from the last round
00232         ScorchedClient::instance()->getActionController().clear();
00233 
00234         // Tell all tanks to update transient settings
00235         ScorchedClient::instance()->getTankContainer().clientNewGame();
00236 
00237         // As we have not returned to the main loop for ages the
00238         // timer will have a lot of time in it
00239         // Get rid of this time so we don't screw things up
00240         ScorchedClient::instance()->getMainLoop().getTimer().getTimeDifference();
00241 
00242         // Reset camera positions for each tank
00243         std::map<unsigned int, Tank *>::iterator tankItor;
00244         for (tankItor = ScorchedClient::instance()->getTankContainer().getAllTanks().begin();
00245                 tankItor != ScorchedClient::instance()->getTankContainer().getAllTanks().end();
00246                 tankItor++)
00247         {
00248                 Tank *current = (*tankItor).second;
00249                 current->getRenderer()->moved();
00250                 current->getCamera().setCameraType(1);
00251         }
00252         MainCamera::instance()->getTarget().setCameraType(TargetCamera::CamSpectator);
00253 
00254         // Tell the server we have finished processing the landscape
00255         ClientWaitState::instance()->sendClientReady();
00256         ClientReloadAdaptor::instance();
00257 
00258         // Move into the wait state
00259         ScorchedClient::instance()->getGameState().stimulate(ClientState::StimWait);
00260         ScorchedClient::instance()->getGameState().checkStimulate();
00261 
00262         return true;
00263 }
00264 
00265 void ClientNewGameHandler::removeTargets()
00266 {
00267         std::map<unsigned int, Target *> targets = // Note copy
00268                 ScorchedClient::instance()->getTargetContainer().getTargets();
00269         std::map<unsigned int, Target *>::iterator itor;
00270         for (itor = targets.begin();
00271                 itor != targets.end();
00272                 itor++)
00273         {
00274                 unsigned int playerId = (*itor).first;
00275                 Target *target = (*itor).second;
00276                 if (target->isTemp())
00277                 {
00278                         if (target->isTarget())
00279                         {
00280                                 Target *removedTarget = 
00281                                         ScorchedClient::instance()->getTargetContainer().removeTarget(playerId);
00282                                 delete removedTarget;
00283                         }
00284                         else
00285                         {
00286                                 Tank *removedTank = 
00287                                         ScorchedClient::instance()->getTankContainer().removeTank(playerId);
00288                                 delete removedTank;
00289                         }
00290                 }
00291         }
00292 }

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