1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
4 // This file is part of Scorched3D.
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>
26 #include <client/ScorchedClient.h>
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>
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();
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();
85 Target
*target
= (*itor
).second
;
86 buffer
.addToBuffer(target
->getPlayerId());
88 if (target
->isTarget())
90 if (!target
->writeMessage(buffer
)) return false;
94 if (!((Tank
*)target
)->writeMessage(buffer
, true)) return false;
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
)
116 snprintf(buffer
, 256, "SyncCheckLog-%u-", time(0));
117 syncCheckFileLogger
= new FileLogger(buffer
);
120 LoggerInfo
info(message
.c_str());
122 syncCheckFileLogger
->logMessage(info
);
125 bool ComsSyncCheckMessage::readMessage(NetBufferReader
&reader
)
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;
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",
155 clientsync
.c_str()));
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
);
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()));
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",
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
++)
210 int x2
= (x
* map
.getMapWidth()) / newMap
.getWidth();
211 int y2
= (y
* map
.getMapHeight()) / newMap
.getHeight();
212 if (heightDiff
[x2
+ y2
* map
.getMapWidth()])
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;
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
);
244 syncCheckLog(S3D::formatStringBuffer(
245 "SyncCheck %i - Failed to find a client target : %u", syncCount
, playerId
));
250 if (target
->isTarget())
252 target
->writeMessage(tmpBuffer
);
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",
269 target
->getCStrName().c_str(), i
));
272 Logger::addLogger(syncCheckFileLogger
);
274 // Only used for step-through debugging to see where the
276 tmpBuffer
.setBufferUsed(i
);
277 NetBufferReader
tmpReader(tmpBuffer
);
278 target
->readMessage(tmpReader
);
280 Logger::remLogger(syncCheckFileLogger
);
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);
296 static Tank
*tmpTank
= new Tank(
297 ScorchedClient::instance()->getContext(),
301 Vector::getNullVector(),
304 if (!tmpTank
->readMessage(reader
)) return false;
305 tmpTank
->getState().setState(TankState::sDead
);
306 tmpTank
->getLife().setLife(0);
307 tmpTank
->getState().setState(TankState::sDead
);
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",
327 ScorchedClient::instance()->getOptionsTransient().getCurrentGameNo()));
330 if (syncCheckFileLogger
)
332 syncCheckLog(S3D::formatStringBuffer("SyncCheck %i checked. (%i syncs)", syncCount
, serverSyncNo
));
336 Logger::log(S3D::formatStringBuffer("SyncCheck %i checked. (%i syncs)", syncCount
, serverSyncNo
));
342 #else // #ifndef S3D_SERVER
344 bool ComsSyncCheckMessage::readMessage(NetBufferReader
&reader
)
349 #endif // #ifndef S3D_SERVER