Merge from development branch heightmap to main.
[scorched3d.git] / src / common / coms / ComsSyncCheckMessage.cpp
blobf87b8d103f3638ba952ae0a02215979f48039b22
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2003
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <coms/ComsSyncCheckMessage.h>
22 #include <common/Logger.h>
23 #include <common/OptionsTransient.h>
24 #include <engine/ActionController.h>
25 #ifndef S3D_SERVER
26 #include <client/ScorchedClient.h>
27 #endif
28 #include <server/ScorchedServer.h>
29 #include <target/TargetContainer.h>
30 #include <target/TargetState.h>
31 #include <target/TargetLife.h>
32 #include <tank/TankState.h>
33 #include <tank/Tank.h>
34 #include <landscapemap/LandscapeMaps.h>
35 #include <set>
37 ComsSyncCheckMessage::ComsSyncCheckMessage() :
38 ComsMessage("ComsSyncCheckMessage")
43 ComsSyncCheckMessage::~ComsSyncCheckMessage()
48 bool ComsSyncCheckMessage::writeMessage(NetBuffer &buffer)
50 // Send action sync data
51 std::vector<std::string>::iterator syncItor;
52 std::vector<std::string> &syncs =
53 ScorchedServer::instance()->getActionController().getSyncCheck();
54 buffer.addToBuffer((int) syncs.size());
55 for (syncItor = syncs.begin();
56 syncItor != syncs.end();
57 syncItor++)
59 buffer.addToBuffer(syncItor->c_str());
62 // Send the height map data
63 HeightMap &map = ScorchedServer::instance()->getLandscapeMaps().
64 getGroundMaps().getHeightMap();
65 for (int y=0; y<map.getMapHeight(); y++)
67 for (int x=0; x<map.getMapWidth(); x++)
69 fixed height = map.getHeight(x, y);
70 buffer.addToBuffer(height);
71 FixedVector &normal = map.getNormal(x, y);
72 buffer.addToBuffer(normal);
76 // Send the target data
77 std::map<unsigned int, Target *> &possibletargets =
78 ScorchedServer::instance()->getTargetContainer().getTargets();
79 std::map<unsigned int, Target *>::iterator itor;
80 buffer.addToBuffer((int) possibletargets.size());
81 for (itor = possibletargets.begin();
82 itor != possibletargets.end();
83 itor++)
85 Target *target = (*itor).second;
86 buffer.addToBuffer(target->getPlayerId());
88 if (target->isTarget())
90 if (!target->writeMessage(buffer)) return false;
92 else
94 if (!((Tank*)target)->writeMessage(buffer, true)) return false;
98 return true;
101 #ifndef S3D_SERVER
103 #include <common/FileLogger.h>
104 #include <image/ImageFactory.h>
105 #include <landscape/Landscape.h>
107 static FileLogger *syncCheckFileLogger = 0;
109 static int syncCount = 0;
111 static void syncCheckLog(const std::string &message)
113 if (!syncCheckFileLogger)
115 char buffer[256];
116 snprintf(buffer, 256, "SyncCheckLog-%u-", time(0));
117 syncCheckFileLogger = new FileLogger(buffer);
120 LoggerInfo info(message.c_str());
121 info.setTime();
122 syncCheckFileLogger->logMessage(info);
125 bool ComsSyncCheckMessage::readMessage(NetBufferReader &reader)
127 syncCount++;
129 std::vector<std::string> &clientsyncs =
130 ScorchedClient::instance()->getActionController().getSyncCheck();
131 int serverSyncNo = 0, clientSyncNo = (int) clientsyncs.size();
132 if (!reader.getFromBuffer(serverSyncNo)) return false;
134 bool printOutput = false;
135 std::string output;
136 for (int s=0; s<MAX(serverSyncNo, clientSyncNo); s++)
138 std::string clientsync, serversync;
139 if (s < serverSyncNo)
141 if (!reader.getFromBuffer(serversync)) return false;
143 if (s < clientSyncNo)
145 clientsync = clientsyncs[s];
148 bool diff = (serversync != clientsync);
149 if (diff) printOutput = true;
151 output.append(S3D::formatStringBuffer("%i: %s %s ::: %s\n",
152 syncCount,
153 (diff?"***":""),
154 serversync.c_str(),
155 clientsync.c_str()));
157 if (printOutput)
159 syncCheckLog(output.c_str());
162 // Read the height map data
163 HeightMap &map = ScorchedClient::instance()->getLandscapeMaps().
164 getGroundMaps().getHeightMap();
165 int heightDiffs = 0, normalDiffs = 0;
166 bool *heightDiff = new bool[map.getMapHeight() * map.getMapWidth()];
167 for (int y=0; y<map.getMapHeight(); y++)
169 for (int x=0; x<map.getMapWidth(); x++)
171 fixed actualheight = map.getHeight(x, y);
172 FixedVector actualnormal = map.getNormal(x, y);
173 fixed sentheight;
174 FixedVector sentnormal;
175 if (!reader.getFromBuffer(sentheight)) return false;
176 if (!reader.getFromBuffer(sentnormal)) return false;
178 if (actualheight != sentheight)
180 syncCheckLog(S3D::formatStringBuffer("%i %i",
181 actualheight.getInternal(), sentheight.getInternal()));
182 heightDiffs++;
184 if (actualnormal != sentnormal) normalDiffs++;
186 heightDiff[x + y * map.getMapWidth()] = (actualheight != sentheight);
189 if (heightDiffs > 0 || normalDiffs > 0)
191 syncCheckLog(S3D::formatStringBuffer(
192 "SyncCheck %i - Height diffs %i, Normal diffs %i",
193 syncCount,
194 heightDiffs, normalDiffs));
196 ImageHandle newMap = ImageFactory::createBlank(
197 Landscape::instance()->getMainMap().getWidth(),
198 Landscape::instance()->getMainMap().getHeight());
200 GLubyte *dest = newMap.getBits();
201 GLubyte *src = Landscape::instance()->getMainMap().getBits();
202 for (int y=0; y<newMap.getHeight(); y++)
204 for (int x=0; x<newMap.getWidth(); x++)
206 GLubyte r = src[0];
207 GLubyte g = src[1];
208 GLubyte b = src[2];
210 int x2 = (x * map.getMapWidth()) / newMap.getWidth();
211 int y2 = (y * map.getMapHeight()) / newMap.getHeight();
212 if (heightDiff[x2 + y2 * map.getMapWidth()])
214 r = g = b = 255;
217 dest[0] = r;
218 dest[1] = g;
219 dest[2] = b;
221 dest+=3;
222 src+=3;
225 Landscape::instance()->getMainTexture().replace(newMap, false);
226 Landscape::instance()->setTextureType(Landscape::eOther);
229 // Read the target data
230 std::set<unsigned int> readTargets;
231 int numberTargetsSend = 0;
232 NetBuffer tmpBuffer;
234 if (!reader.getFromBuffer(numberTargetsSend)) return false;
235 for (int i=0; i<numberTargetsSend; i++)
237 unsigned int playerId = 0;
238 if (!reader.getFromBuffer(playerId)) return false;
239 readTargets.insert(playerId);
241 Target *target = ScorchedClient::instance()->getTargetContainer().getTargetById(playerId);
242 if (!target)
244 syncCheckLog(S3D::formatStringBuffer(
245 "SyncCheck %i - Failed to find a client target : %u", syncCount, playerId));
246 return true;
249 tmpBuffer.reset();
250 if (target->isTarget())
252 target->writeMessage(tmpBuffer);
254 else
256 ((Tank*)target)->writeMessage(tmpBuffer, true);
259 bool different = false;
260 if (!target->getTargetState().getMovement())
262 for (unsigned int i=0; i<tmpBuffer.getBufferUsed(); i++)
264 if (reader.getReadSize() + i >= reader.getBufferSize() ||
265 tmpBuffer.getBuffer()[i] != reader.getBuffer()[reader.getReadSize() + i])
267 syncCheckLog(S3D::formatStringBuffer("SyncCheck %i - Targets values differ : %u:%s, position %i",
268 syncCount, playerId,
269 target->getCStrName().c_str(), i));
271 different = true;
272 Logger::addLogger(syncCheckFileLogger);
274 // Only used for step-through debugging to see where the
275 // differences are
276 tmpBuffer.setBufferUsed(i);
277 NetBufferReader tmpReader(tmpBuffer);
278 target->readMessage(tmpReader);
280 Logger::remLogger(syncCheckFileLogger);
282 break;
287 if (target->isTarget())
289 static Target *tmpTarget = new Target(0, LangString(),
290 ScorchedClient::instance()->getContext());
291 if (!tmpTarget->readMessage(reader)) return false;
292 tmpTarget->getLife().setLife(0);
294 else
296 static Tank *tmpTank = new Tank(
297 ScorchedClient::instance()->getContext(),
300 LangString(),
301 Vector::getNullVector(),
303 "");
304 if (!tmpTank->readMessage(reader)) return false;
305 tmpTank->getState().setState(TankState::sDead);
306 tmpTank->getLife().setLife(0);
307 tmpTank->getState().setState(TankState::sDead);
309 if (different)
311 syncCheckLog(S3D::formatStringBuffer("%s %s",
312 tmpTank->getState().getStateString(),
313 ((Tank*)target)->getState().getStateString()));
317 if (reader.getBufferSize() != reader.getReadSize())
319 syncCheckLog(S3D::formatStringBuffer("SyncCheck not all bytes read : %i %i,%i",
320 syncCount, reader.getBufferSize(), reader.getReadSize()));
323 if (syncCheckFileLogger)
325 syncCheckLog(S3D::formatStringBuffer("SyncCheck : %i,%i",
326 syncCount,
327 ScorchedClient::instance()->getOptionsTransient().getCurrentGameNo()));
330 if (syncCheckFileLogger)
332 syncCheckLog(S3D::formatStringBuffer("SyncCheck %i checked. (%i syncs)", syncCount, serverSyncNo));
334 else
336 Logger::log(S3D::formatStringBuffer("SyncCheck %i checked. (%i syncs)", syncCount, serverSyncNo));
339 return true;
342 #else // #ifndef S3D_SERVER
344 bool ComsSyncCheckMessage::readMessage(NetBufferReader &reader)
346 return true;
349 #endif // #ifndef S3D_SERVER