1 /* -*- Mode: C++; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*-
2 *
3 * Quadra, an action puzzle game
4 * Copyright (C) 1998-2000 Ludus Design
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This program 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include "packets.h"
21
22 #include "net_buf.h"
23 #include "error.h"
24 #include "net_stuff.h"
25 #include "stats.h"
26 #include "cfgfile.h"
27 #include "canvas.h"
28
29 using std::vector;
30
write(Net_buf * p)31 void Packet_wantjoin::write(Net_buf *p) {
32 Packet_ping::write(p);
33 p->write_byte(1);
34 p->write_byte(net_version);
35 p->write_byte(language);
36 p->write_byte(os);
37 p->write_bool(true);
38 }
39
read(Net_buf * p)40 bool Packet_wantjoin::read(Net_buf *p) {
41 if(!Packet_ping::read(p))
42 return false;
43 if(!p->read_byte())
44 return false; // completely ignore 1.1.0 clients
45 net_version=p->read_byte();
46 language=p->read_byte();
47 os=p->read_byte();
48 p->read_bool();
49 return true;
50 }
51
read_attack(Attack * a,Net_buf * p)52 bool read_attack(Attack *a, Net_buf *p) {
53 a->type=(Attack_type) p->read_byte();
54 if(a->type>=ATTACK_LAST)
55 return false;
56 a->param=p->read_dword();
57 return true;
58 }
59
write_attack(Attack * a,Net_buf * p)60 void write_attack(Attack *a, Net_buf *p) {
61 p->write_byte(a->type);
62 p->write_dword(a->param);
63 }
64
Packet_gameinfo()65 Packet_gameinfo::Packet_gameinfo() {
66 packet_id = P_GAMEINFO;
67 name[0] = 0;
68 version = 0;
69 port = 0;
70 game_end_value = 0;
71 nolevel_up = 0;
72 delay_start = false;
73 terminated = false;
74 level_start = 0;
75 combo_min = 0;
76 allow_handicap = true;
77 survivor = false;
78 hot_potato = false;
79 game_end = 0;
80 }
81
~Packet_gameinfo()82 Packet_gameinfo::~Packet_gameinfo() {
83 while (!players.empty()) {
84 delete players.back();
85 players.pop_back();
86 }
87 }
88
write(Net_buf * p)89 void Packet_gameinfo::write(Net_buf *p) {
90 Packet_udp::write(p);
91 p->write_string(name);
92 p->write_byte(version);
93 p->write_dword(port);
94 p->write_byte(players.size());
95 vector<Net_player*>::const_iterator it;
96 for (it = players.begin(); it != players.end(); ++it) {
97 p->write_byte((*it)->team);
98 p->write_string((*it)->name);
99 }
100 p->write_dword(game_end_value);
101 p->write_bool(nolevel_up);
102 p->write_bool(delay_start);
103 p->write_bool(terminated);
104 p->write_byte(level_start);
105 p->write_byte(combo_min);
106 p->write_bool(survivor);
107 p->write_byte(game_end);
108 for (it = players.begin(); it != players.end(); ++it)
109 p->write_dword((*it)->handicap);
110 //allow_handicap is reversed because the default should be true
111 // but 1.1.1 and older will not supply it (thus we'll read a
112 // 0 from those).
113 p->write_bool(!allow_handicap);
114 p->write_bool(hot_potato);
115 if(version>=22) {
116 write_attack(&normal_attack, p);
117 write_attack(&clean_attack, p);
118 write_attack(&potato_normal_attack, p);
119 write_attack(&potato_clean_attack, p);
120 }
121 }
122
read(Net_buf * p)123 bool Packet_gameinfo::read(Net_buf *p) {
124 if(!Packet_udp::read(p))
125 return false;
126 if(!p->read_string(name, sizeof(name)))
127 return false;
128 version = p->read_byte();
129 port = p->read_dword();
130 Byte num_player = p->read_byte();
131 if(num_player>MAXPLAYERS)
132 return false;
133 int i;
134 for(i=0; i<num_player; i++) {
135 char tmp[40];
136 Byte t=p->read_byte();
137 if(t>=MAXTEAMS)
138 return false;
139 if(!p->read_string(tmp, sizeof(tmp)))
140 return false;
141 add_player(0, t, tmp, -1, 0);
142 }
143 game_end_value = p->read_dword();
144 nolevel_up = p->read_bool();
145 delay_start = p->read_bool();
146 terminated = p->read_bool();
147 level_start = p->read_byte();
148 if(level_start > 10)
149 return false;
150 combo_min = p->read_byte();
151 if(combo_min > 10)
152 return false;
153 survivor = p->read_bool();
154 game_end = p->read_byte();
155 if(game_end > 4)
156 return false;
157 for(i=0; i<num_player; i++) {
158 int handicap;
159 handicap = p->read_dword();
160 if(handicap<0 || handicap>4)
161 return false;
162 players[i]->handicap=handicap;
163 }
164 //allow_handicap is reversed because the default should be true
165 // but 1.1.1 and older will not supply it (thus we'll read a
166 // 0 from those).
167 allow_handicap=!p->read_bool();
168 hot_potato=p->read_bool();
169 if(version>=22) {
170 if(!read_attack(&normal_attack, p))
171 return false;
172 if(!read_attack(&clean_attack, p))
173 return false;
174 if(!read_attack(&potato_normal_attack, p))
175 return false;
176 if(!read_attack(&potato_clean_attack, p))
177 return false;
178 }
179 return true;
180 }
181
~Packet_gameserver()182 Packet_gameserver::~Packet_gameserver() {
183 while (!players.empty()) {
184 delete players.back();
185 players.pop_back();
186 }
187 }
188
write(Net_buf * p)189 void Packet_gameserver::write(Net_buf *p) {
190 Packet_ping::write(p);
191 p->write_byte(version);
192 p->write_string(name);
193 p->write_bool(accepted);
194 p->write_dword(game_seed);
195 p->write_bool(paused);
196 p->write_byte(players.size());
197 p->write_bool(nolevel_up);
198 p->write_byte(level_start);
199 p->write_bool(survivor);
200 p->write_byte(combo_min);
201 p->write_word(delay_start);
202 p->write_byte(game_end);
203 p->write_dword(game_end_value);
204 vector<Net_player*>::const_iterator it;
205 for (it = players.begin(); it != players.end(); ++it) {
206 p->write_byte((*it)->quel);
207 p->write_byte((*it)->team);
208 p->write_string((*it)->name);
209 }
210 p->write_bool(wants_moves);
211 p->write_byte(syncpoint);
212 p->write_byte(potato_team);
213 for (it = players.begin(); it != players.end(); ++it)
214 p->write_dword((*it)->handicap);
215 //allow_handicap is reversed because the default should be true
216 // but 1.1.1 and older will not supply it (thus we'll read a
217 // 0 from those).
218 p->write_bool(!allow_handicap);
219 p->write_bool(hot_potato);
220 if(version>=22) {
221 write_attack(&normal_attack, p);
222 write_attack(&clean_attack, p);
223 write_attack(&potato_normal_attack, p);
224 write_attack(&potato_clean_attack, p);
225 }
226 p->write_bool(single);
227 p->write_bool(terminated);
228 for (it = players.begin(); it != players.end(); ++it)
229 p->write_dword((*it)->player_id);
230 p->write_bool(boring_rules);
231 }
232
read(Net_buf * p)233 bool Packet_gameserver::read(Net_buf *p) {
234 if(!Packet_ping::read(p))
235 return false;
236 version = p->read_byte();
237 if(!p->read_string(name, sizeof(name)))
238 return false;
239 accepted=p->read_bool();
240 game_seed=p->read_dword();
241 paused=p->read_bool();
242 Byte num_player = p->read_byte();
243 if(num_player>MAXPLAYERS)
244 return false;
245 nolevel_up=p->read_bool();
246 level_start=p->read_byte();
247 survivor=p->read_bool();
248 combo_min=p->read_byte();
249 delay_start=p->read_word();
250 game_end=p->read_byte();
251 if(game_end>=END_LAST)
252 return false;
253 game_end_value=p->read_dword();
254 int i;
255 for(i=0; i<num_player; i++) {
256 char tmp[40];
257 Byte quel=p->read_byte();
258 if(quel>=MAXPLAYERS)
259 return false;
260 Byte t=p->read_byte();
261 if(t>=MAXTEAMS)
262 return false;
263 if(!p->read_string(tmp, sizeof(tmp)))
264 return false;
265 add_player(quel, t, tmp, 0, 0);
266 }
267 wants_moves=p->read_bool();
268 syncpoint=p->read_byte();
269 if(syncpoint>Canvas::LAST)
270 return false;
271 potato_team=p->read_byte();
272 if(potato_team>=MAXTEAMS && potato_team!=255)
273 return false;
274 //Adjust player handicaps (they are at the end to maintain
275 // net compatibility with net_version <= 20
276 for(i=0; i<num_player; i++) {
277 int handicap=p->read_dword();
278 if(handicap<0 || handicap>4)
279 return false;
280 players[i]->handicap = handicap;
281 }
282 //allow_handicap is reversed because the default should be true
283 // but 1.1.1 and older will not supply it (thus we'll read a
284 // 0 from those).
285 allow_handicap=!p->read_bool();
286 hot_potato=p->read_bool();
287 if(version>=22) {
288 if(!read_attack(&normal_attack, p))
289 return false;
290 if(!read_attack(&clean_attack, p))
291 return false;
292 if(!read_attack(&potato_normal_attack, p))
293 return false;
294 if(!read_attack(&potato_clean_attack, p))
295 return false;
296 }
297 single=p->read_bool();
298 terminated=p->read_bool();
299 for (i = 0; i < num_player; ++i)
300 players[i]->player_id = p->read_dword();
301 boring_rules=p->read_bool();
302 return true;
303 }
304
any_attack()305 bool Packet_gameserver::any_attack() {
306 if(normal_attack.type!=ATTACK_NONE || clean_attack.type!=ATTACK_NONE)
307 return true;
308 if(hot_potato && (potato_normal_attack.type!=ATTACK_NONE || potato_clean_attack.type!=ATTACK_NONE))
309 return true;
310 return false;
311 }
312
read(Net_buf * p)313 bool Packet_chat::read(Net_buf *p) {
314 if(!Packet_tcp::read(p))
315 return false;
316 team = p->read_byte();
317 if(team>=MAXTEAMS || team<-1)
318 return false;
319 if(!p->read_string(text, sizeof(text)))
320 return false;
321 to_team = p->read_byte();
322 if(to_team>=MAXTEAMS || to_team<-1)
323 return false;
324 return true;
325 }
326
write(Net_buf * p)327 void Packet_chat::write(Net_buf *p) {
328 Packet_tcp::write(p);
329 p->write_byte(team);
330 p->write_string(text);
331 p->write_byte(to_team);
332 }
333
read(Net_buf * p)334 bool Packet_playerwantjoin::read(Net_buf *p) {
335 if(!Packet_ping::read(p))
336 return false;
337 team = p->read_byte();
338 if(team>=MAXTEAMS)
339 return false;
340 if(!p->read_string(name, sizeof(name)))
341 return false;
342 player = p->read_byte();
343 if(player>2)
344 return false;
345 int repeat = p->read_dword();
346 if(repeat<-1 || repeat>3)
347 return false;
348 smooth = p->read_dword();
349 if(smooth<0 || smooth>1)
350 return false;
351 shadow = p->read_dword();
352 if(shadow<0 || shadow>1)
353 return false;
354 handicap = p->read_dword();
355 if(handicap<0 || handicap>4)
356 return false;
357 p->read_mem(player_hash, sizeof(player_hash));
358 if(!p->read_string(team_name, sizeof(team_name)))
359 return false;
360 p->read_mem(team_hash, sizeof(team_hash));
361 h_repeat = p->read_dword();
362 if(h_repeat<0 || h_repeat>3)
363 return false;
364 v_repeat = p->read_dword();
365 if(v_repeat<0 || v_repeat>3)
366 return false;
367 return true;
368 }
369
write(Net_buf * p)370 void Packet_playerwantjoin::write(Net_buf *p) {
371 Packet_ping::write(p);
372 p->write_byte(team);
373 p->write_string(name);
374 p->write_byte(player);
375 if(game->net_version()>=23)
376 p->write_dword(static_cast<Dword>(-1));
377 else
378 p->write_dword(h_repeat);
379 p->write_dword(smooth);
380 p->write_dword(shadow);
381 p->write_dword(handicap);
382 p->write_mem(player_hash, sizeof(player_hash));
383 p->write_string(team_name);
384 p->write_mem(team_hash, sizeof(team_hash));
385 p->write_dword(h_repeat);
386 p->write_dword(v_repeat);
387 }
388
read(Net_buf * p)389 bool Packet_player::read(Net_buf *p) {
390 if(!Packet_ping::read(p))
391 return false;
392 team = p->read_byte();
393 if(team>=MAXTEAMS)
394 return false;
395 if(!p->read_string(name, sizeof(name)))
396 return false;
397 player = p->read_byte();
398 if(player>2)
399 return false;
400 int repeat = p->read_dword();
401 if(repeat<-1 || repeat>3)
402 return false;
403 if(repeat!=-1)
404 h_repeat = v_repeat = repeat;
405 smooth = p->read_dword();
406 if(smooth<0 || smooth>1)
407 return false;
408 shadow = p->read_dword();
409 if(shadow<0 || shadow>1)
410 return false;
411 pos = p->read_byte();
412 if(pos>=MAXPLAYERS)
413 return false;
414 handicap = p->read_dword();
415 if(handicap<0 || handicap>4)
416 return false;
417 int h_repeat = p->read_dword();
418 if(h_repeat<0 || h_repeat>3)
419 return false;
420 if(repeat==-1 || h_repeat)
421 this->h_repeat = h_repeat;
422 int v_repeat = p->read_dword();
423 if(v_repeat<0 || v_repeat>3)
424 return false;
425 if(repeat==-1 || v_repeat)
426 this->v_repeat = v_repeat;
427 player_id = p->read_dword();
428 return true;
429 }
430
write(Net_buf * p)431 void Packet_player::write(Net_buf *p) {
432 Packet_ping::write(p);
433 p->write_byte(team);
434 p->write_string(name);
435 p->write_byte(player);
436 if(game->net_version()>=23)
437 p->write_dword(static_cast<Dword>(-1));
438 else
439 p->write_dword(h_repeat);
440 p->write_dword(smooth);
441 p->write_dword(shadow);
442 p->write_byte(pos);
443 p->write_dword(handicap);
444 p->write_dword(h_repeat);
445 p->write_dword(v_repeat);
446 p->write_dword(player_id);
447 }
448
read(Net_buf * p)449 bool Packet_playeraccepted::read(Net_buf *p) {
450 if(!Packet_ping::read(p))
451 return false;
452 pos = p->read_byte();
453 if(pos>=MAXPLAYERS)
454 return false;
455 accepted = p->read_byte();
456 return true;
457 }
458
write(Net_buf * p)459 void Packet_playeraccepted::write(Net_buf *p) {
460 Packet_ping::write(p);
461 p->write_byte(pos);
462 p->write_byte(accepted);
463 }
464
read(Net_buf * p)465 bool Packet_pause::read(Net_buf *p) {
466 if(!Packet_tcp::read(p))
467 return false;
468 player=p->read_byte();
469 return true;
470 }
471
write(Net_buf * p)472 void Packet_pause::write(Net_buf *p) {
473 Packet_tcp::write(p);
474 p->write_byte(player);
475 }
476
~Packet_stat()477 Packet_stat::~Packet_stat() {
478 while (!net_stats.empty()) {
479 delete net_stats.back();
480 net_stats.pop_back();
481 }
482 }
483
add_stat(Byte s,int v)484 void Packet_stat::add_stat(Byte s, int v) {
485 net_stats.push_back(new Net_stat(s, v));
486 }
487
read(Net_buf * p)488 bool Packet_stat::read(Net_buf *p) {
489 if(!Packet_playerbase::read(p))
490 return false;
491 num_stat=p->read_byte();
492 for(int i=0; i<num_stat; i++) {
493 Byte st=p->read_byte();
494 int val=p->read_dword();
495 if(st>=CS::LAST)
496 continue; //Ignore stats we don't know about
497 add_stat(st, val);
498 }
499 return true;
500 }
501
write(Net_buf * p)502 void Packet_stat::write(Net_buf *p) {
503 Packet_playerbase::write(p);
504 p->write_byte(net_stats.size());
505 vector<Net_stat*>::const_iterator it;
506 for (it = net_stats.begin(); it != net_stats.end(); ++it) {
507 p->write_byte((*it)->st);
508 p->write_dword((*it)->value);
509 }
510 }
511
~Packet_gamestat()512 Packet_gamestat::~Packet_gamestat() {
513 while (!net_stats.empty()) {
514 delete net_stats.back();
515 net_stats.pop_back();
516 }
517 }
518
add_stat(Byte s,int v)519 void Packet_gamestat::add_stat(Byte s, int v) {
520 net_stats.push_back(new Net_stat(s, v));
521 }
522
read(Net_buf * p)523 bool Packet_gamestat::read(Net_buf *p) {
524 if(!Packet_tcp::read(p))
525 return false;
526 num_stat=p->read_byte();
527 for(int i=0; i<num_stat; i++) {
528 Byte st=p->read_byte();
529 int val=p->read_dword();
530 if(st>=GS::LAST)
531 continue; //Ignore stats we don't know about
532 add_stat(st, val);
533 }
534 return true;
535 }
536
write(Net_buf * p)537 void Packet_gamestat::write(Net_buf *p) {
538 Packet_tcp::write(p);
539 p->write_byte(net_stats.size());
540 vector<Net_stat*>::const_iterator it;
541 for (it = net_stats.begin(); it != net_stats.end(); ++it) {
542 p->write_byte((*it)->st);
543 p->write_dword((*it)->value);
544 }
545 }
546
read(Net_buf * p)547 bool Packet_dropplayer::read(Net_buf *p) {
548 if(!Packet_playerbase::read(p))
549 return false;
550 Byte r=p->read_byte();
551 if(r>=DROP_LAST)
552 return false;
553 reason=(Drop_reason) r;
554 return true;
555 }
556
write(Net_buf * p)557 void Packet_dropplayer::write(Net_buf *p) {
558 Packet_playerbase::write(p);
559 p->write_byte(reason);
560 }
561
read(Net_buf * p)562 bool Packet_playerbase::read(Net_buf *p) {
563 if(!Packet_tcp::read(p))
564 return false;
565 player=p->read_byte();
566 if(player>=MAXPLAYERS)
567 return false;
568 return true;
569 }
570
write(Net_buf * p)571 void Packet_playerbase::write(Net_buf *p) {
572 Packet_tcp::write(p);
573 p->write_byte(player);
574 }
575
read(Net_buf * p)576 bool Packet_stampblock::read(Net_buf *p) {
577 if(!Packet_playerbase::read(p))
578 return false;
579 x=p->read_byte();
580 y=p->read_byte();
581 rotate=p->read_byte();
582 score=p->read_byte();
583 date=p->read_word();
584 block_rotated=p->read_byte();
585 time_held=p->read_word();
586 return true;
587 }
588
write(Net_buf * p)589 void Packet_stampblock::write(Net_buf *p) {
590 Packet_playerbase::write(p);
591 p->write_byte(x);
592 p->write_byte(y);
593 p->write_byte(rotate);
594 p->write_byte(score);
595 p->write_word(date);
596 p->write_byte(block_rotated);
597 p->write_word(time_held);
598 }
599
read(Net_buf * p)600 bool Packet_dead::read(Net_buf *p) {
601 if(!Packet_playerbase::read(p))
602 return false;
603 then_gone=p->read_bool();
604 return true;
605 }
606
write(Net_buf * p)607 void Packet_dead::write(Net_buf *p) {
608 Packet_playerbase::write(p);
609 p->write_bool(then_gone);
610 }
611
read(Net_buf * p)612 bool Packet_startwatch::read(Net_buf *p) {
613 if(!Packet_playerbase::read(p))
614 return false;
615 address=p->read_dword();
616 stop=p->read_bool();
617 update=p->read_byte();
618 return true;
619 }
620
write(Net_buf * p)621 void Packet_startwatch::write(Net_buf *p) {
622 Packet_playerbase::write(p);
623 p->write_dword(address);
624 p->write_bool(stop);
625 p->write_byte(update);
626 }
627
read(Net_buf * p)628 bool Packet_download::read(Net_buf *p) {
629 if(!Packet_playerbase::read(p))
630 return false;
631 p->read_mem(can, sizeof(can));
632 int i, j;
633 for(j=0; j<32; j++)
634 for(i=0; i<10; i++) {
635 occ[j][i]=can[j][i]? true:false;
636 can[j][i] &= 0x7F;
637 }
638 seed = p->read_dword();
639 idle = p->read_byte();
640 if(idle>3)
641 return false;
642 state = p->read_byte();
643 if(state>Canvas::LAST)
644 return false;
645 bloc = p->read_byte();
646 if(bloc>6 && bloc!=255)
647 return false;
648 next = p->read_byte();
649 if(next>6 && bloc!=255)
650 return false;
651 next2 = p->read_byte();
652 if(next2>6 && bloc!=255)
653 return false;
654 next3 = p->read_byte();
655 if(next3>6 && bloc!=255)
656 return false;
657 bonus = p->read_byte();
658 if(bonus>20)
659 return false;
660 for(i=0; i<20; i++) {
661 if(i<bonus) {
662 bon[i].x=p->read_byte();
663 bon[i].color=p->read_byte();
664 bon[i].blind_time=0; //Will be fixed below
665 bon[i].hole_pos=0;
666 bon[i].final=false;
667 }
668 else {
669 p->read_byte();
670 p->read_byte();
671 bon[i].x=0;
672 bon[i].color=0;
673 bon[i].blind_time=0;
674 bon[i].hole_pos=0;
675 bon[i].final=false;
676 }
677 }
678 for(i=0; i<MAXPLAYERS; i++)
679 attacks[i] = p->read_byte();
680 last_attacker = p->read_byte();
681 if(last_attacker>=MAXPLAYERS && last_attacker!=255)
682 return false;
683 p->read_mem(blinded, sizeof(blinded));
684 for(i=0; i<20; i++)
685 if(i<bonus)
686 bon[i].blind_time=p->read_byte();
687 else
688 p->read_byte();
689 for(i=0; i<bonus; i++) {
690 Word tmp=p->read_word();
691 bon[i].hole_pos=tmp & 0x3FF;
692 bon[i].final=tmp&0x8000? true:false;
693 }
694 return true;
695 }
696
write(Net_buf * p)697 void Packet_download::write(Net_buf *p) {
698 Packet_playerbase::write(p);
699 Byte tmp[32][10];
700 memcpy(tmp, can, sizeof(can));
701 int i, j;
702 if(game->net_version()>=23)
703 for(j=0; j<32; j++)
704 for(i=0; i<10; i++)
705 if(occ[j][i])
706 tmp[j][i] |= 0x80;
707 p->write_mem(tmp, sizeof(can));
708 p->write_dword(seed);
709 p->write_byte(idle);
710 p->write_byte(state);
711 p->write_byte(bloc);
712 p->write_byte(next);
713 p->write_byte(next2);
714 p->write_byte(next3);
715 p->write_byte(bonus);
716 for(i=0; i<20; i++)
717 if(i<bonus) {
718 p->write_byte(bon[i].x);
719 p->write_byte(bon[i].color);
720 }
721 else {
722 p->write_byte(0);
723 p->write_byte(0);
724 }
725 for(i=0; i<MAXPLAYERS; i++)
726 p->write_byte(attacks[i]);
727 p->write_byte(last_attacker);
728 p->write_mem(blinded, sizeof(blinded));
729 for(i=0; i<20; i++)
730 if(i<bonus)
731 p->write_byte(bon[i].blind_time);
732 else
733 p->write_byte(0);
734 for(i=0; i<bonus; i++) {
735 Word tmp=bon[i].hole_pos;
736 if(bon[i].final)
737 tmp |= 0x8000;
738 p->write_word(tmp);
739 }
740 }
741
read(Net_buf * p)742 bool Packet_lines::read(Net_buf *p) {
743 if(!Packet_playerbase::read(p))
744 return false;
745 nb=p->read_byte();
746 if(nb>36)
747 return false;
748 nc=p->read_byte();
749 lx=p->read_byte();
750 //127 is magical code for new complexity stuff
751 if((lx<4 || lx>=14) && lx!=127)
752 return false;
753 sender=p->read_byte();
754 if(sender>=MAXPLAYERS && sender!=255)
755 return false;
756 attack.type=(Attack_type) p->read_byte();
757 if(attack.type>=ATTACK_LAST)
758 return false;
759 attack.param=p->read_dword();
760 for(int i=0; i<nb; i++)
761 hole_pos[i]=p->read_word();
762 return true;
763 }
764
write(Net_buf * p)765 void Packet_lines::write(Net_buf *p) {
766 Packet_playerbase::write(p);
767 p->write_byte(nb);
768 p->write_byte(nc);
769 p->write_byte(lx);
770 p->write_byte(sender);
771 p->write_byte(attack.type);
772 p->write_dword(attack.param);
773 for(int i=0; i<nb; i++)
774 p->write_word(hole_pos[i]);
775 }
776
read(Net_buf * p)777 bool Packet_testping::read(Net_buf *p) {
778 if(!Packet_tcp::read(p))
779 return false;
780 frame=p->read_dword();
781 return true;
782 }
783
write(Net_buf * p)784 void Packet_testping::write(Net_buf *p) {
785 Packet_tcp::write(p);
786 p->write_dword(frame);
787 }
788
read(Net_buf * p)789 bool Packet_gone::read(Net_buf *p) {
790 if(!Packet_playerbase::read(p))
791 return false;
792 chat_msg=!p->read_bool();
793 return true;
794 }
795
write(Net_buf * p)796 void Packet_gone::write(Net_buf *p) {
797 Packet_playerbase::write(p);
798 p->write_bool(!chat_msg);
799 }
800
read(Net_buf * p)801 bool Packet_endgame::read(Net_buf *p) {
802 if(!Packet_tcp::read(p))
803 return false;
804 auto_end=p->read_bool();
805 return true;
806 }
807
write(Net_buf * p)808 void Packet_endgame::write(Net_buf *p) {
809 Packet_tcp::write(p);
810 p->write_bool(auto_end);
811 }
812
read(Net_buf * p)813 bool Packet_rejoin::read(Net_buf *p) {
814 if(!Packet_playerbase::read(p))
815 return false;
816 int repeat = p->read_dword();
817 if(repeat<-1 || repeat>3)
818 return false;
819 smooth = p->read_dword();
820 if(smooth<0 || smooth>1)
821 return false;
822 shadow = p->read_dword();
823 if(shadow<0 || shadow>1)
824 return false;
825 handicap = p->read_dword();
826 if(handicap<0 || handicap>4)
827 return false;
828 h_repeat = p->read_dword();
829 if(h_repeat<0 || h_repeat>3)
830 return false;
831 v_repeat = p->read_dword();
832 if(v_repeat<0 || v_repeat>3)
833 return false;
834 return true;
835 }
836
write(Net_buf * p)837 void Packet_rejoin::write(Net_buf *p) {
838 Packet_playerbase::write(p);
839 if(game->net_version()>=23)
840 p->write_dword(static_cast<Dword>(-1));
841 else
842 p->write_dword(h_repeat);
843 p->write_dword(smooth);
844 p->write_dword(shadow);
845 p->write_dword(handicap);
846 p->write_dword(h_repeat);
847 p->write_dword(v_repeat);
848 }
849
850
start_byte()851 void Packet_moves::start_byte() {
852 if(size==255)
853 fatal_msgbox("Packet_moves too big!");
854 moves[size]=0;
855 }
856
set_bit(int v)857 void Packet_moves::set_bit(int v) {
858 moves[size] |= v;
859 }
860
write_byte()861 void Packet_moves::write_byte() {
862 size++;
863 }
864
read(Net_buf * p)865 bool Packet_moves::read(Net_buf *p) {
866 if(!Packet_playerbase::read(p))
867 return false;
868 size=p->read_byte();
869 p->read_mem(moves, size);
870 return true;
871 }
872
write(Net_buf * p)873 void Packet_moves::write(Net_buf *p) {
874 Packet_playerbase::write(p);
875 p->write_byte(size);
876 p->write_mem(moves, size);
877 }
878
read(Net_buf * p)879 bool Packet_state::read(Net_buf *p) {
880 if(!Packet_playerbase::read(p))
881 return false;
882 state=p->read_byte();
883 if(state>Canvas::LAST)
884 return false;
885 return true;
886 }
887
write(Net_buf * p)888 void Packet_state::write(Net_buf *p) {
889 Packet_playerbase::write(p);
890 p->write_byte(state);
891 }
892
write(Net_buf * p)893 void Packet_serverrandom::write(Net_buf *p) {
894 Packet_tcp::write(p);
895 p->write_dword(seed);
896 }
897
read(Net_buf * p)898 bool Packet_serverrandom::read(Net_buf *p) {
899 if(!Packet_tcp::read(p))
900 return false;
901 seed=p->read_dword();
902 return true;
903 }
904
read(Net_buf * p)905 bool Packet_serverpotato::read(Net_buf *p) {
906 if(!Packet_tcp::read(p))
907 return false;
908 team=p->read_byte();
909 if(team>=MAXTEAMS && team!=255)
910 return false;
911 potato_lines=p->read_dword();
912 return true;
913 }
914
write(Net_buf * p)915 void Packet_serverpotato::write(Net_buf *p) {
916 Packet_tcp::write(p);
917 p->write_byte(team);
918 p->write_dword(potato_lines);
919 }
920
write(Net_buf * p)921 void Packet_servernameteam::write(Net_buf *p) {
922 Packet_tcp::write(p);
923 p->write_byte(team);
924 p->write_string(name);
925 }
926
read(Net_buf * p)927 bool Packet_servernameteam::read(Net_buf *p) {
928 if(!Packet_tcp::read(p))
929 return false;
930 team=p->read_byte();
931 if(team>=MAXTEAMS)
932 return false;
933 if(!p->read_string(name, sizeof(name)))
934 return false;
935 return true;
936 }
937
Var()938 Packet_serverlog::Var::Var() {
939 name[0]=0;
940 value[0]=0;
941 }
942
Var(const char * n,const char * val)943 Packet_serverlog::Var::Var(const char* n, const char* val) {
944 strncpy(name, n, sizeof(name));
945 name[sizeof(name)-1]=0;
946 strncpy(value, val, sizeof(value));
947 value[sizeof(value)-1]=0;
948 }
949
Var(const char * n,unsigned i)950 Packet_serverlog::Var::Var(const char* n, unsigned i) {
951 strncpy(name, n, sizeof(name));
952 name[sizeof(name)-1]=0;
953 sprintf(value, "%u", i);
954 }
955
Var(const char * n,int i)956 Packet_serverlog::Var::Var(const char* n, int i) {
957 strncpy(name, n, sizeof(name));
958 name[sizeof(name)-1]=0;
959 sprintf(value, "%i", i);
960 }
961
Var(const char * n,float f)962 Packet_serverlog::Var::Var(const char* n, float f) {
963 strncpy(name, n, sizeof(name));
964 name[sizeof(name)-1]=0;
965 sprintf(value, "%f", f);
966 }
967
Packet_serverlog(const char * type)968 Packet_serverlog::Packet_serverlog(const char* type) {
969 packet_id = P_SERVERLOG;
970 strncpy(event_type, type, sizeof(event_type));
971 event_type[sizeof(event_type)-1]=0;
972 }
973
read(Net_buf * p)974 bool Packet_serverlog::Var::read(Net_buf* p) {
975 if(!p->read_string(name, sizeof(name)))
976 return false;
977 if(!p->read_string(value, sizeof(value)))
978 return false;
979 return true;
980 }
981
write(Net_buf * p)982 void Packet_serverlog::Var::write(Net_buf* p) {
983 p->write_string(name);
984 p->write_string(value);
985 }
986
write(Net_buf * p)987 void Packet_serverlog::write(Net_buf* p) {
988 Packet_tcp::write(p);
989 p->write_string(event_type);
990 p->write_dword(vars.size());
991 vector<Var>::iterator it;
992 for (it = vars.begin(); it != vars.end(); ++it)
993 it->write(p);
994 }
995
read(Net_buf * p)996 bool Packet_serverlog::read(Net_buf* p) {
997 if(!Packet_tcp::read(p))
998 return false;
999 if(!p->read_string(event_type, sizeof(event_type)))
1000 return false;
1001 vars.clear();
1002 unsigned size = p->read_dword();
1003 if(size > 100)
1004 return false;
1005 for(unsigned i=0; i<size; i++) {
1006 Var v;
1007 if(!v.read(p))
1008 return false;
1009 vars.push_back(v);
1010 }
1011 return true;
1012 }
1013
add(const Var & var)1014 void Packet_serverlog::add(const Var& var)
1015 {
1016 vars.push_back(var);
1017 }
1018