ComsSyncCheckMessage.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 <coms/ComsSyncCheckMessage.h>
00022 #include <common/Logger.h>
00023 #include <common/OptionsTransient.h>
00024 #include <engine/ActionController.h>
00025 #ifndef S3D_SERVER
00026         #include <client/ScorchedClient.h>
00027 #endif
00028 #include <server/ScorchedServer.h>
00029 #include <target/TargetContainer.h>
00030 #include <target/TargetState.h>
00031 #include <target/TargetLife.h>
00032 #include <tank/TankState.h>
00033 #include <tank/TankScore.h>
00034 #include <tank/Tank.h>
00035 #include <landscapemap/LandscapeMaps.h>
00036 #include <set>
00037 
00038 ComsSyncCheckMessage::ComsSyncCheckMessage() :
00039         ComsMessage("ComsSyncCheckMessage")
00040 {
00041 
00042 }
00043 
00044 ComsSyncCheckMessage::~ComsSyncCheckMessage()
00045 {
00046 
00047 }
00048 
00049 bool ComsSyncCheckMessage::writeMessage(NetBuffer &buffer)
00050 {
00051         // Send action sync data
00052         std::vector<std::string>::iterator syncItor;
00053         std::vector<std::string> &syncs = 
00054                 ScorchedServer::instance()->getActionController().getSyncCheck();
00055         buffer.addToBuffer((int) syncs.size());
00056         for (syncItor = syncs.begin();
00057                 syncItor != syncs.end();
00058                 syncItor++)
00059         {
00060                 buffer.addToBuffer(syncItor->c_str());
00061         }
00062 
00063         // Send the height map data
00064         HeightMap &map = ScorchedServer::instance()->getLandscapeMaps().
00065                 getGroundMaps().getHeightMap();
00066         for (int y=0; y<map.getMapHeight(); y++)
00067         {
00068                 for (int x=0; x<map.getMapWidth(); x++)
00069                 {
00070                         fixed height = map.getHeight(x, y);
00071                         buffer.addToBuffer(height);
00072                         FixedVector &normal = map.getNormal(x, y);
00073                         buffer.addToBuffer(normal);
00074                 }
00075         }
00076 
00077         // Send the target data
00078         std::map<unsigned int, Target *> &possibletargets =
00079                         ScorchedServer::instance()->getTargetContainer().getTargets();
00080         std::map<unsigned int, Target *>::iterator itor;
00081         buffer.addToBuffer((int) possibletargets.size());
00082         for (itor = possibletargets.begin();
00083                 itor != possibletargets.end();
00084                 itor++)
00085         {
00086                 Target *target = (*itor).second;
00087                 buffer.addToBuffer(target->getPlayerId());
00088 
00089                 if (target->isTarget())
00090                 {
00091                         if (!target->writeMessage(buffer)) return false;
00092                 }
00093                 else
00094                 {
00095                         if (!((Tank*)target)->writeMessage(buffer, true)) return false;
00096                 }
00097         }
00098 
00099         return true;
00100 }
00101 
00102 #ifndef S3D_SERVER
00103 
00104 #include <common/FileLogger.h>
00105 #include <image/ImageFactory.h>
00106 #include <landscape/Landscape.h>
00107 
00108 static FileLogger *syncCheckFileLogger = 0;
00109 
00110 static int syncCount = 0;
00111 
00112 static void syncCheckLog(const std::string &message)
00113 {
00114         if (!syncCheckFileLogger) 
00115         {
00116                 char buffer[256];
00117                 snprintf(buffer, 256, "SyncCheckLog-%u-", time(0));
00118                 syncCheckFileLogger = new FileLogger(buffer);
00119         }       
00120 
00121         LoggerInfo info(message.c_str());
00122         info.setTime();
00123         syncCheckFileLogger->logMessage(info);
00124 }
00125 
00126 bool ComsSyncCheckMessage::readMessage(NetBufferReader &reader)
00127 {
00128         syncCount++;
00129 
00130         std::vector<std::string> &clientsyncs = 
00131                 ScorchedClient::instance()->getActionController().getSyncCheck();
00132         int serverSyncNo = 0, clientSyncNo = (int) clientsyncs.size();
00133         if (!reader.getFromBuffer(serverSyncNo)) return false;
00134 
00135         bool printOutput = false;
00136         std::string output = S3D::formatStringBuffer(
00137                 "SyncCheck %i - Action Diffs",
00138                 syncCount);
00139         for (int s=0; s<MAX(serverSyncNo, clientSyncNo); s++)
00140         {
00141                 std::string clientsync, serversync;
00142                 if (s < serverSyncNo)
00143                 {
00144                         if (!reader.getFromBuffer(serversync)) return false;
00145                 }
00146                 if (s < clientSyncNo)
00147                 {
00148                         clientsync = clientsyncs[s];
00149                 }
00150 
00151                 bool diff = (serversync != clientsync);
00152                 if (diff) printOutput = true;
00153 
00154                 output.append(S3D::formatStringBuffer("%i: %s \n  %s\n  %s\n", 
00155                         syncCount,
00156                         (diff?"***":""),
00157                         serversync.c_str(), 
00158                         clientsync.c_str()));
00159         }
00160         if (printOutput)
00161         {
00162                 syncCheckLog(output.c_str());
00163         }
00164 
00165         // Read the height map data
00166         HeightMap &map = ScorchedClient::instance()->getLandscapeMaps().
00167                 getGroundMaps().getHeightMap();
00168         int heightDiffs = 0, normalDiffs = 0;
00169         bool *heightDiff = new bool[map.getMapHeight() * map.getMapWidth()];
00170         for (int y=0; y<map.getMapHeight(); y++)
00171         {
00172                 for (int x=0; x<map.getMapWidth(); x++)
00173                 {
00174                         fixed actualheight = map.getHeight(x, y);
00175                         FixedVector actualnormal = map.getNormal(x, y);
00176                         fixed sentheight;
00177                         FixedVector sentnormal;
00178                         if (!reader.getFromBuffer(sentheight)) return false;
00179                         if (!reader.getFromBuffer(sentnormal)) return false;
00180                         
00181                         if (actualheight != sentheight) 
00182                         {
00183                                 syncCheckLog(S3D::formatStringBuffer("*** %i %i", 
00184                                         actualheight.getInternal(), sentheight.getInternal()));
00185                                 heightDiffs++;
00186                         }
00187                         if (actualnormal != sentnormal) normalDiffs++;
00188 
00189                         heightDiff[x + y * map.getMapWidth()] = (actualheight != sentheight);
00190                 }
00191         }
00192         if (heightDiffs > 0 || normalDiffs > 0)
00193         {
00194                 syncCheckLog(S3D::formatStringBuffer(
00195                         "SyncCheck %i - Height diffs %i, Normal diffs %i",
00196                         syncCount,
00197                         heightDiffs, normalDiffs));
00198         
00199                 ImageHandle newMap = ImageFactory::createBlank(
00200                         Landscape::instance()->getMainMap().getWidth(),
00201                         Landscape::instance()->getMainMap().getHeight());
00202 
00203                 GLubyte *dest = newMap.getBits();
00204                 GLubyte *src = Landscape::instance()->getMainMap().getBits();
00205                 for (int y=0; y<newMap.getHeight(); y++)
00206                 {
00207                         for (int x=0; x<newMap.getWidth(); x++)
00208                         {
00209                                 GLubyte r = src[0];
00210                                 GLubyte g = src[1];
00211                                 GLubyte b = src[2];
00212 
00213                                 int x2 = (x * map.getMapWidth()) / newMap.getWidth();
00214                                 int y2 = (y * map.getMapHeight()) / newMap.getHeight();
00215                                 if (heightDiff[x2 + y2 * map.getMapWidth()])
00216                                 {
00217                                         r = g = b = 255;
00218                                 }
00219                 
00220                                 dest[0] = r;
00221                                 dest[1] = g;
00222                                 dest[2] = b;
00223 
00224                                 dest+=3;
00225                                 src+=3;
00226                         }
00227                 }
00228                 Landscape::instance()->getMainTexture().replace(newMap, false);
00229                 Landscape::instance()->setTextureType(Landscape::eOther);
00230         }
00231 
00232         // Read the target data
00233         std::set<unsigned int> readTargets;
00234         int numberTargetsSend = 0;
00235         NetBuffer tmpBuffer;
00236 
00237         // Create temporary target/tanks
00238         static Target *tmpTarget = new Target(0, LangString(),
00239                 ScorchedClient::instance()->getContext());
00240         tmpTarget->getLife().setLife(0); // Make sure not added to target space
00241         static Tank *tmpTank = new Tank(
00242                 ScorchedClient::instance()->getContext(),
00243                 0,
00244                 0, 
00245                 LangString(),
00246                 Vector::getNullVector(),
00247                 "",
00248                 "");
00249         tmpTank->getState().setState(TankState::sDead); // Make sure not added to target space
00250 
00251         if (!reader.getFromBuffer(numberTargetsSend)) return false;
00252         for (int i=0; i<numberTargetsSend; i++)
00253         {
00254                 unsigned int playerId = 0;
00255                 if (!reader.getFromBuffer(playerId)) return false;
00256                 readTargets.insert(playerId);
00257 
00258                 Target *target = ScorchedClient::instance()->getTargetContainer().getTargetById(playerId);
00259                 if (!target)
00260                 {
00261                         syncCheckLog(S3D::formatStringBuffer(
00262                                 "SyncCheck %i - Failed to find a client target : %u", syncCount, playerId));
00263                         return true;
00264                 }
00265 
00266                 tmpBuffer.reset();
00267                 if (target->isTarget())
00268                 {
00269                         target->writeMessage(tmpBuffer);
00270                 }
00271                 else
00272                 {
00273                         ((Tank*)target)->writeMessage(tmpBuffer, true);
00274                 }
00275 
00276                 bool different = false;
00277                 if (!target->getTargetState().getMovement())
00278                 {
00279                         for (unsigned int i=0; i<tmpBuffer.getBufferUsed(); i++)
00280                         {
00281                                 if (reader.getReadSize() + i >= reader.getBufferSize())
00282                                 {
00283                                         syncCheckLog(S3D::formatStringBuffer(
00284                                                 "SyncCheck %i - Targets premature end of buffer : %u:%s, position %i", 
00285                                                 syncCount, playerId, 
00286                                                 target->getCStrName().c_str(), i));
00287 
00288                                         different = true;
00289                                         break;
00290                                 }
00291                                 else if(tmpBuffer.getBuffer()[i] != reader.getBuffer()[reader.getReadSize() + i])
00292                                 {
00293                                         syncCheckLog(S3D::formatStringBuffer(
00294                                                 "SyncCheck %i - Targets values differ : %u:%s, position %i", 
00295                                                 syncCount, playerId, 
00296                                                 target->getCStrName().c_str(), i));
00297 
00298                                         different = true;
00299                                         Logger::addLogger(syncCheckFileLogger);
00300 
00301                                         // Only used for step-through debugging and logging to see where the
00302                                         // differences are
00303                                         tmpBuffer.setBufferUsed(i);
00304                                         NetBufferReader tmpReader(tmpBuffer);
00305                                         if (target->isTarget())
00306                                         {
00307                                                 tmpTarget->readMessage(tmpReader);
00308                                                 tmpTarget->getLife().setLife(0);// Make sure not added to target space
00309                                         }
00310                                         else
00311                                         {
00312                                                 tmpTank->readMessage(tmpReader);
00313                                                 tmpTank->getState().setState(TankState::sDead);// Make sure not added to target space
00314                                         }
00315 
00316                                         Logger::remLogger(syncCheckFileLogger);
00317                                         break;
00318                                 }
00319                         }
00320                 }
00321 
00322                 if (target->isTarget())
00323                 {
00324                         if (!tmpTarget->readMessage(reader)) return false;
00325                         tmpTarget->getLife().setLife(0);// Make sure not added to target space
00326                 }
00327                 else
00328                 {
00329                         if (!tmpTank->readMessage(reader)) return false;
00330 
00331                         if (different)
00332                         {
00333                                 syncCheckLog(S3D::formatStringBuffer("Server : %s:%s", 
00334                                         tmpTank->getState().getStateString(),
00335                                         tmpTank->getScore().getScoreString()));
00336                                 syncCheckLog(S3D::formatStringBuffer("Client : %s:%s", 
00337                                         ((Tank*)target)->getState().getStateString(),
00338                                         ((Tank*)target)->getScore().getScoreString()));
00339                         }
00340 
00341                         tmpTank->getState().setState(TankState::sDead);// Make sure not added to target space
00342                 }
00343         }
00344         if (reader.getBufferSize() != reader.getReadSize())
00345         {
00346                 syncCheckLog(S3D::formatStringBuffer("SyncCheck not all bytes read : %i   %i,%i",
00347                         syncCount, reader.getBufferSize(), reader.getReadSize()));
00348         }
00349 
00350         if (syncCheckFileLogger)
00351         {
00352                 syncCheckLog(S3D::formatStringBuffer("SyncCheck : %i,%i",
00353                         syncCount,
00354                         ScorchedClient::instance()->getOptionsTransient().getCurrentGameNo()));
00355         }
00356 
00357         if (syncCheckFileLogger)
00358         {
00359                 syncCheckLog(S3D::formatStringBuffer("SyncCheck %i checked. (%i syncs)", syncCount, serverSyncNo));
00360         }
00361         else
00362         {
00363                 Logger::log(S3D::formatStringBuffer("SyncCheck %i checked. (%i syncs)", syncCount, serverSyncNo));
00364         }
00365 
00366         return true;
00367 }
00368 
00369 #else // #ifndef S3D_SERVER
00370 
00371 bool ComsSyncCheckMessage::readMessage(NetBufferReader &reader)
00372 {
00373         return true;
00374 }
00375 
00376 #endif // #ifndef S3D_SERVER

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