1 /*
2 This program is free software; you can redistribute it and/or
3 modify it under the terms of the GNU General Public License
4 as published by the Free Software Foundation; either version 2
5 of the License, or (at your option) any later version.
6 
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 
11 See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 
17     $Id$
18 */
19 
20 #include "defs.h"
21 
22 void ReadPackets (void);
23 
24 typedef struct
25 {
26 	int		running;
27 	float	time;
28 	float	diff;
29 	float	ratio;
30 	qbool synced;
31 } info_t;
32 
33 static info_t	info[MAX_CLIENTS];
34 static sizebuf_t dummy;
35 
36 enum {T_ENT, T_CL};
37 
FindEntity(int type,frame_t * f,int num,int frame)38 void *FindEntity(int type, frame_t *f, int num, int frame)
39 {
40 	//f = &d->frames[frame&UPDATE_MASK];
41 	f += frame&UPDATE_MASK;
42 
43 	switch (type)
44 	{
45 	case T_ENT:
46 		{
47 			packet_entities_t *p;
48 			int i;
49 
50 			if (f->invalid)
51 				return NULL;
52 
53 			p = &f->packet_entities;
54 			for (i = 0; i < p->num_entities; i++)
55 				if (p->entities[i].number == num)
56 					return &p->entities[i];
57 
58 			return NULL;
59 		}
60 
61 	case T_CL:
62 		if (f->playerstate[num].messagenum == frame)
63 			return &f->playerstate[num];
64 
65 		return NULL;
66 	default:
67 		return NULL;
68 	}
69 }
70 
app(vec3_t o1,vec3_t po1,vec3_t o2,vec3_t po2,float * sec,float t1,float t2)71 qbool app (vec3_t o1, vec3_t po1, vec3_t o2, vec3_t po2, float *sec, float t1, float t2)
72 {
73 	int i,j;
74 
75 	for (i = 0; i < 3; i++)
76 		if (o1[i] - po1[i] != 0)
77 			break;
78 
79 	for (j = 0; j < 3; j++)
80 		if (o2[j] - po2[j] != 0)
81 			break;
82 
83 	if (i == 3)
84 		return false;
85 
86 	if (j == 3)
87 		return false;
88 
89 	if (po1[i] >= o2[i] && o1[i] <= o2[i] && po1[i] <= po2[i])
90 	{
91 		*sec = (o2[i] - o1[i])*t1/(po1[i] - o1[i]);
92 		//Sys_Printf("app:%f, %f, %f %f (%f %f)\n", o1[i], o2[i], po1[i], po2[i], t1, t2);
93 		return true;
94 	}
95 
96 	if (po1[i] <= o2[i] && o1[i] >= o2[i] && po1[i] >= po2[i])
97 	{
98 		*sec = (o2[i] - o1[i])*t1/(o1[i] - po1[i]);
99 		//Sys_Printf("app:%f, %f, %f %f (%f %f)\n", o1[i], o2[i], po1[i], po2[i], t1, t2);
100 		return true;
101 	}
102 
103 	if (po2[j] >= o1[j] && o2[j] <= o1[j] && po2[j] <= po1[j])
104 	{
105 		*sec = (o1[j] - o2[j])*t2/(po2[j] - o2[j]);
106 		//Sys_Printf("app:%f, %f, %f %f (%f %f)\n", o1[i], o2[i], po1[i], po2[i], t1, t2);
107 		return true;
108 	}
109 
110 	if (po2[j] <= o1[j] && o2[j] >= o1[j] && po2[j] >= po1[j])
111 	{
112 		*sec = (o1[j] - o2[j])*t2/(o2[j] - po2[j]);
113 		//Sys_Printf("app:%f, %f, %f %f (%f %f)\n", o1[i], o2[i], po1[i], po2[i], t1, t2);
114 		return true;
115 	}
116 
117 	//Sys_Printf("false\n");
118 
119 	return false;
120 }
121 
122 #define depth 3
demcmp(source_t * d1,source_t * d2)123 float demcmp(source_t *d1, source_t *d2)
124 {
125 	frame_t *f1, *f2;
126 	packet_entities_t *e1, *e2;
127 	player_state_t *p1, *p2, *op1, *op2;
128 	entity_state_t *pe1, *pe2;
129 	int i,j, c, k, p;
130 	float	sr;
131 	vec3_t vec;
132 
133 	if (!d1->running)
134 		return -1;
135 	if (!d2->running)
136 		return -1;
137 
138 	f1 = &d1->frames[d1->parsecount&UPDATE_MASK];
139 	f2 = &d2->frames[d2->parsecount&UPDATE_MASK];
140 
141 	if (f1->invalid)
142 		return -1;
143 	if (f2->invalid)
144 		return -1;
145 
146 	c = 0;
147 	sr = 0;
148 	p = 0;
149 	// compare players
150 	p1 = f1->playerstate;
151 	p2 = f2->playerstate;
152 	for (i = 0; i < MAX_CLIENTS; i++, p1++, p2++)
153 	{
154 		if (p1->messagenum != d1->parsecount)
155 			continue;
156 		if (p2->messagenum != d2->parsecount)
157 			continue;
158 
159 		//VectorSubtract(p1->origin, p2->origin, vec);
160 
161 		for (k = 1; k < depth; k++)
162 		{
163 			op1 = (player_state_t*)FindEntity(T_CL, d1->frames, i, d1->parsecount - k);
164 
165 			if (!op1)
166 				continue;
167 
168 			VectorSubtract(p1->origin, op1->origin, vec);
169 			if (VectorLength(vec) > 0 && VectorLength(vec) < 100)
170 				break;
171 		}
172 
173 		if (k == depth)
174 			op1 = NULL;
175 
176 		for (k = 1; k < depth; k++)
177 		{
178 			op2 = (player_state_t*)FindEntity(T_CL, d2->frames, i, d2->parsecount - k);
179 
180 			if (!op2)
181 				continue;
182 
183 			VectorSubtract(p2->origin, op2->origin, vec);
184 			if (VectorLength(vec) > 0 && VectorLength(vec) < 100)
185 				break;
186 		}
187 
188 		if (k == depth)
189 			op2 = NULL;
190 
191 		if (op1 && op2)
192 		{
193 			vec3_t vec2;
194 
195 			VectorSubtract(p1->origin, p2->origin, vec);
196 			VectorSubtract(p1->origin, op1->origin, vec2);
197 			//Sys_Printf("ent:%d %f\n",e1->entities[i].number, VectorLength(vec)/VectorLength(vec2));
198 			//return VectorLength(vec)/VectorLength(vec2);
199 			sr += VectorLength(vec)/VectorLength(vec2);
200 			c++;
201 		}
202 
203 		//sr += VectorLength(vec);
204 		//c++;
205 		//p++;
206 		//if (VectorLength(vec))
207 		//	Sys_Printf("cl:%d %f %s\n", i, VectorLength(vec), d1->players[i].name);
208 	}
209 
210 	// compare entities
211 	i = 0;
212 	j = 0;
213 
214 	e1 = &f1->packet_entities;
215 	e2 = &f2->packet_entities;
216 
217 	while (i < e1->num_entities && j < e2->num_entities)
218 	{
219 		if (e1->entities[i].number < e2->entities[j].number)
220 			i++;
221 		else if (e1->entities[i].number > e2->entities[j].number)
222 			j++;
223 		else
224 		{
225 			for (k = 1; k < depth; k++)
226 			{
227 				pe1 = (entity_state_t*)FindEntity(T_ENT, d1->frames, e1->entities[i].number, d1->parsecount - k);
228 
229 				if (!pe1)
230 					continue;
231 
232 				VectorSubtract(e1->entities[i].origin, pe1->origin, vec);
233 				if (VectorLength(vec) > 0)
234 					break;
235 			}
236 
237 			if (k == depth)
238 				pe1 = NULL;
239 
240 			for (k = 1; k < depth; k++)
241 			{
242 				pe2 = (entity_state_t*)FindEntity(T_ENT, d2->frames, e2->entities[j].number, d2->parsecount - k);
243 
244 				if (!pe2)
245 					continue;
246 
247 				VectorSubtract(e2->entities[j].origin, pe2->origin, vec);
248 				if (VectorLength(vec) > 0)
249 					break;
250 			}
251 			if (k == depth)
252 				pe2 = NULL;
253 
254 			if (pe1 && pe2)
255 			{
256 				vec3_t vec2;
257 
258 				VectorSubtract(e1->entities[i].origin, e2->entities[j].origin, vec);
259 				VectorSubtract(e1->entities[i].origin, pe1->origin, vec2);
260 				//Sys_Printf("ent:%d %f\n",e1->entities[i].number, VectorLength(vec)/VectorLength(vec2));
261 				//return VectorLength(vec)/VectorLength(vec2);
262 				sr += VectorLength(vec)/VectorLength(vec2);
263 				c++;
264 			}
265 
266 			i++;
267 			j++;
268 		}
269 	}
270 
271 	if (!c)
272 		return -1;
273 
274 	return sr/c;
275 }
276 
SetComparisionDemo(source_t * dem,float time1)277 qbool SetComparisionDemo(source_t *dem, float time1)
278 {
279 	int num;
280 
281 	from = dem;
282 	num = from - sources;
283 
284 	dem->running = (1 << (dem - sources));
285 	if (from->lastframe > time1) // rewind
286 	{
287 		from->netchan.incoming_sequence = 0;
288 		from->netchan.incoming_acknowledged= 0;
289 		from->netchan.incoming_reliable_acknowledged = 0;
290 		from->prevtime = 0;
291 		from->time = from->worldtime = from->lastframe = from->lasttime = 0;
292 		from->latency = 0;
293 		from->parsecount = 0;
294 		rewind(sworld.from[from-sources].file);
295 		from->lastframe = -1;
296 		ReadPackets();
297 	}
298 
299 	if (time1 > (from->lastframe))
300 		from->lastframe = time1;
301 
302 	ReadPackets();
303 
304 	return from->running != 0;
305 }
306 
307 
Synchronize(void)308 qbool Synchronize (void)
309 {
310 	int i, j, bad;
311 	info_t *p;
312 	source_t *dem1, *dem2;
313 	float prevdesync = 0.0, before = 0.0, after = 0.0, diff, desync = 0.0, f = 0.0, newdesync = 0.0, x = 0.0, y = 0.0, mindiff = 0.0, m = 0.0, sr = 0.0, c = 0.0, sr2 = 0.0, sec2 = 0.0, test = 0.0, test2 = 0.0;
314 	byte buf[15*MAX_MSGLEN];
315 	qbool done;
316 
317 	if (sworld.fromcount == 1)
318 		return true;
319 
320 	sworld.options |= O_QWDSYNC;
321 
322 	memset(&dummy, 0, sizeof(dummy));
323 	dummy.data = buf;
324 	dummy.maxsize = sizeof(buf);
325 
326 	msgbuf = &dummy;
327 	world.time = 0;
328 
329 	// get starting info about demos
330 	for (p = info, from = sources; from - sources < sworld.fromcount; from++, p++)
331 	{
332 		if (!from->running)
333 			continue;
334 
335 		rewind(sworld.from[from-sources].file);
336 		memset(&from->netchan, 0, sizeof(from->netchan));
337 		from->latency = from->worldtime = from->lastframe = from->lasttime = 0.0; // float
338 		from->prevtime = 0; // long
339 		from->parsecount = 0; // int
340 
341 		p->running = from->running;
342 		p->diff = 0;
343 		p->synced = false;
344 		from->lastframe = -1;
345 		ReadPackets();
346 		p->time = from->time;
347 		p->ratio = 1;
348 	}
349 
350 	dem1 = sources;
351 	info[0].synced = true;
352 
353 	// now read another demo and try to compare
354 	for (i = 1, dem2 = sources + 1; i < sworld.fromcount; dem2++, i++)
355 	{
356 		if (!dem2->running)
357 			continue;
358 
359 		// initial guess for time desync
360 		x = 1;
361 		y = info[i].time - info[0].time;
362 		// rewind dem1
363 		if (!SetComparisionDemo(dem1, info->time))
364 		{
365 			sworld.options -= O_QWDSYNC;
366 			return false;
367 		}
368 
369 		// read 10 sec from dem2
370 		while (dem1->running)
371 		{
372 			j = 0;
373 			diff = 0;
374 			if (!dem2->running)
375 				SetComparisionDemo(dem2, info[i].time);
376 
377 			while (dem1->running && dem2->running && dem2->time - dem1->time < x + y)
378 			{
379 				if (diff <0)
380 				{
381 					f = dem2->time - dem1->time;
382 
383 					from = dem1;
384 					from->lastframe += 1;
385 					ReadPackets();
386 
387 					from = dem2;
388 					while (from->running && from->time < dem1->time + f)
389 						ReadPackets();
390 				}
391 				else
392 				{
393 					from = dem2;
394 					ReadPackets();
395 				}
396 
397 				diff = demcmp(dem1, dem2);
398 
399 				//Sys_Printf("diff:%f, %f, %f %f\n", diff, dem2->worldtime - dem1->worldtime, dem1->worldtime, dem2->worldtime);
400 
401 				if (diff < 0 || diff > 5)
402 					continue;
403 
404 				f = dem2->time + 1;
405 				desync = dem1->time - dem2->time;
406 				from = dem2;
407 
408 				//Sys_Printf("diff:%f, desync:%f\n", diff, desync);
409 				while (from->running && from->time < f)
410 				{
411 					ReadPackets();
412 					m = demcmp(dem1, dem2);
413 					if (m < 0 || m >= diff)
414 						continue;
415 
416 					diff = m;
417 					desync = dem1->time - dem2->time;
418 				}
419 
420 				//Sys_Printf("diff:%f, desync:%f\n", diff, desync);
421 
422 				bad = 0;
423 				j = 0;
424 				sr = 0;
425 				c = 0;
426 				sr2 = 0;
427 
428 				//dem1->lastframe += 1;
429 				test = desync;
430 
431 				while (dem1->running && dem2->running && bad < 5 && j < 30)
432 				{
433 					from = dem1;
434 					//from->lastframe += 0.5;
435 					f = from->time + 0.5;
436 					while (from->running && from->time < f)
437 						ReadPackets();
438 
439 					from = dem2;
440 					f = -1;
441 					m = -1;
442 					while (from->running && from->time + desync < dem1->time + 0.25)
443 					{
444 						ReadPackets();
445 						m = demcmp(dem1, dem2);
446 						if ( m < 0)
447 							continue;
448 
449 						if (f < 0 || f > m)
450 						{
451 							f = m;
452 							newdesync = dem1->time - dem2->time;
453 						}
454 					}
455 
456 					//m = demcmp(dem1, dem2);
457 
458 					if (f < 0)
459 						continue;
460 
461 					//Sys_Printf("diff:%f\n", f);
462 					if (f > 1)
463 					{
464 						bad++;
465 						continue;
466 					}
467 
468 					m = newdesync - test;
469 					test += m < 0 ? max(-0.025, m) : min(0.025, m);
470 
471 					if (!f)
472 						f = 0.01f;
473 
474 					f = 1;
475 					sr2 += 1/(f*f);
476 					sr += newdesync/(f*f);
477 					c++;
478 
479 					desync = test;
480 
481 					if (c > 10)
482 						desync = sr/sr2;
483 
484 					j++;
485 				}
486 
487 				//Sys_Printf("\n%f %d %d, %d, %f\n",desync, j , bad, c, x);
488 
489 				if (bad == 5)
490 				{
491 					diff = 0;
492 					continue;
493 				}
494 
495 				if (j == 30)
496 					break;
497 			}
498 
499 			if (j == 30)
500 			{
501 				Sys_Printf("sync1:%f %f\n", desync, sr/sr2);
502 				if (c)
503 					desync = sr/sr2;
504 
505 				desync = test;
506 				before = dem2->time;
507 				prevdesync = desync;
508 
509 
510 				sr = 0;
511 				c = 0;
512 				sr2 = 0;
513 				j = 0;
514 #if 1
515 				//desync = 0.5;
516 				if (desync < 0)
517 				{
518 					SetComparisionDemo(dem1, info->time - desync + 2);
519 					SetComparisionDemo(dem2, 0);
520 				}
521 				else
522 				{
523 					SetComparisionDemo(dem1, info->time + 2);
524 					SetComparisionDemo(dem2, info[i].time + desync);
525 				}
526 
527 				test = desync;
528 
529 				while (dem1->running && dem2->running && j < 800)
530 				{
531 					from = dem1;
532 					f = from->time + 2;
533 					while (from->running && from->time < f)
534 						ReadPackets();
535 					//from->lastframe += 1;
536 					//ReadPackets();
537 
538 					from = dem2;
539 					f = -999;
540 					m = -999;
541 					sec2 = 0;
542 					while (from->running && from->time + desync < dem1->time + 1)
543 					{
544 						ReadPackets();
545 						sec2 = 0;
546 
547 						m = demcmp(dem1, dem2);
548 						if ( m < 0)
549 							continue;
550 
551 						if (f < 0 || f > m)
552 						{
553 							f = m;
554 							newdesync = dem1->time - dem2->time;
555 						}
556 
557 					}
558 
559 					if (fabs(f) < 1)
560 					{
561 						test2 = 0;
562 						m = newdesync - test;
563 						test += m < 0 ? max(-0.025, m) : min(0.025, m);
564 
565 						//Sys_Printf("%f %f %f %f, %f %f\n",newdesync, f, desync, test, dem1->time, dem1->time - newdesync);
566 						if (!f)
567 							f = 0.1f;
568 						f = 1;
569 						sr2 += 1/(f*f);
570 						sr += newdesync/(f*f);
571 						c++;
572 					}
573 					else if (f > 4)
574 					{
575 						test2++;
576 						if (test2 == 5)
577 							Sys_Printf("lag:%f, %d\n", dem1->worldtime, dem2-sources);
578 
579 					}
580 
581 					if (f < 0)
582 						continue;
583 
584 					if (c > 10)
585 						//desync = sr/sr2;
586 						desync = test;
587 
588 					after = dem2->time;
589 					j++;
590 				}
591 				//Sys_Printf("j:%d sync:%f\n", j, desync);
592 
593 				if (c)
594 				{
595 					//desync = sr/sr2;
596 					desync = test;
597 					//Sys_Printf("time:%f, b:%f, a:%f, p:%f, d:%f\n", info[i].time, before, after, prevdesync, desync);
598 					info[i].ratio = (after - before + desync - prevdesync)/(after - before);
599 					//Sys_Printf("ratio:%f\n", info[i].ratio);
600 					f = (desync - prevdesync)/(after - before);
601 					desync += f*(info[i].time - after);
602 				}
603 
604 
605 #endif
606 				info[i].diff = desync;
607 				info[i].synced = true;
608 				if (mindiff > desync)
609 					mindiff = desync;
610 				break;
611 			}
612 
613 			//Sys_Printf("another try\n");
614 			x *= 2;
615 			SetComparisionDemo(dem1, info->time + x);
616 			SetComparisionDemo(dem2, info[i].time);
617 		}
618 
619 	}
620 
621 	done = true;
622 	diff = -1;
623 	for (i = 0, p = info, from = sources; i < sworld.fromcount; i++, p++, from++)
624 	{
625 		if (!p->running)
626 			continue;
627 
628 		from->running = p->running;
629 		rewind(sworld.from[i].file);
630 		from->netchan.incoming_sequence = 0;
631 		from->netchan.incoming_acknowledged = 0;
632 		from->sync = p->diff - mindiff;
633 		from->worldtime = from->latency = from->time = from->lasttime = from->lastframe = 0;
634 		from->prevtime = 0;
635 		from->parsecount = 0;
636 		from->ratio = p->ratio;
637 		if (!p->synced)
638 		{
639 			Sys_Printf(" couldn't synchronize %s\n", sworld.from[i].name);
640 			done = false;
641 		}
642 		else
643 			Sys_Printf(" time offset:%f, time ratio:%f\n", from->sync, from->ratio);
644 
645 		from->lastframe = -1;
646 		ReadPackets();
647 		if (diff < from->worldtime)
648 			diff = from->worldtime;
649 	}
650 
651 	world.signonstats = true;
652 	for (from = sources; from - sources < sworld.fromcount; from++)
653 	{
654 		while (from->running && from->worldtime < diff)
655 			ReadPackets();
656 	}
657 
658 	world.signonstats = false;
659 	sworld.options -= O_QWDSYNC;
660 
661 	return done;
662 }
663