source: abuse/trunk/src/old_server.cpp @ 682

Last change on this file since 682 was 555, checked in by Sam Hocevar, 8 years ago

ps3: make everything compile on the PS3. Of course, nothing links yet
because so much support is missing.

File size: 17.2 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com, by
8 *  Jonathan Clark, or by Sam Hocevar.
9 */
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <unistd.h>
16
17#include "nfserver.h"
18
19#include "server.h"
20#include "view.h"
21#include "dprint.h"
22#include "jnet.h"
23#include "level.h"
24#include "game.h"
25#include "jrand.h"
26#include "timing.h"
27//#include "nfserver.h"
28//#include "nfclient.h"
29
30//nfs_server *file_server=NULL;
31
32int send_pkt(out_socket *o, packet &pk)
33{
34//  while (!o->ready_to_write())
35//    if (file_server) file_server->service_request();
36  return o->send(pk);
37}
38
39
40
41int get_pkt(out_socket *o, packet &pk)
42{
43//  while (!o->ready_to_read())
44//    if (file_server) file_server->service_request();
45  return o->get(pk);
46}
47
48
49
50
51server *game_server;
52int start_running=0,sync_check=0;
53
54void server::remove_from_server(view *f)  // should only be called from client side
55{
56  if (f->connect)
57  {
58    packet pk;
59    uint8_t cmd=SCMD_QUIT;    // send quit command to server
60    pk.write(&cmd,1);
61    send_pkt(f->connect,pk);
62    delete f->connect;
63    f->connect=NULL;
64  }
65}
66
67server::server(int argc, char **argv)
68{
69  char name[200];
70  int port=20202,no_net=0;
71  strcpy(name,getlogin() ? getlogin() : "unknown");
72  in=NULL;
73
74  // see if this computer is net capable
75
76
77  int i;
78  // preprocessing stuff before checking for connect to server
79  for (i=1; i<argc; i++)
80  {
81    if (!strcmp(argv[i],"-port"))
82    {
83      i++;
84      if (sscanf(argv[i],"%d",&port)!=1 || port<1 || port>0xffff)
85      {
86    dprintf("Bad port number, port should be 1..%d\n",0xffff);
87    exit(0);
88      }
89    } else if (!strcmp(argv[i],"-name"))     // name player uses when connecting
90    {
91      i++;
92      strcpy(name,argv[i]);
93    }  else if (!strcmp(argv[i],"-nonet"))
94    {
95      dprintf("Network bypassed, no player will be able to connect\n");
96      no_net=1;
97    } else if (!strcmp(argv[i],"-sync"))
98      sync_check=1;
99
100  }
101
102  if (no_net)
103    has_net=0;
104  else has_net=net_init();
105
106  for (i=1; i<argc; i++)
107  {
108    if (!strcmp(argv[i],"-net"))
109    {
110      if (!has_net)
111      {
112    dprintf("No network detected, load network drivers and try again\n");
113    exit(1);
114      }
115      else
116      {
117    out_socket *os=NULL;
118    i++;
119    dprintf("Trying to connect to server %s on port %d\n",argv[i],port);
120    if (!os=create_out_socket(argv[i],port))
121    {
122      dprintf("%s\n",last_sock_err);
123      dprintf("Make sure server is running...\n");
124      exit(1);
125    }
126    dprintf("Connected!\n");
127
128    join_game(os,name,argv[i]);
129
130      }
131    }
132  }
133
134  if (!player_list)                  // if we are not connecting to a server, become one
135  {
136    is_server=1;
137    if (has_net)
138    {
139      in=new in_socket(port);
140      if (current_sock_err)
141      {
142    dprintf("%s\n",last_sock_err);
143    dprintf("Running single player mode\n");
144    has_net=0;
145      } //else
146//    file_server=new nfs_server(port+1);
147
148    }
149    set_local_players(1);
150  }
151
152}
153
154
155
156
157
158void server::tick()
159{
160//  if (file_server)
161//    file_server->service_request();
162  next_out.reset();          // clear the next packet out..
163  check_for_new_players();
164  collect_inputs();
165}
166
167uint32_t make_sync_uint32()
168{
169  uint32_t x=0;
170  for (view *v=player_list; v; v=v->next)
171  {
172    x^=v->focus->x;
173    x^=v->focus->y;
174  }
175  return x^rand_on;
176}
177
178int server::process_command(view *f, uint8_t command, packet &pk)
179{
180  switch (command)
181  {
182    case SCMD_QUIT :                          // delete player
183    {
184      dprintf("Player %d has quit\n",f->player_number);
185      return 0;
186    } break;
187
188    case SCMD_VIEW_RESIZE :                          // change view area
189    {
190      uint32_t view_size[8];
191      if (pk.read((uint8_t *)view_size,8*4)!=8*4)
192      return 0;
193      else
194      {
195    f->resize_view(lltl(view_size[0]),lltl(view_size[1]),lltl(view_size[2]),lltl(view_size[3]));
196    f->pan_x=lltl(view_size[4]);
197    f->pan_y=lltl(view_size[5]);
198    f->shift_down=lltl(view_size[6]);
199    f->shift_right=lltl(view_size[7]);
200    f->suggest.send_view=0;
201    if (is_server)                  // if we are a server, tell everybody about this.
202    {
203      uint8_t cmd=SCMD_VIEW_RESIZE;
204      next_out.write((uint8_t *)&cmd,1);
205      uint16_t pn=lstl(f->player_number);
206      next_out.write((uint8_t *)&pn,2);
207      next_out.write((uint8_t *)view_size,8*4);
208    }
209      }
210    } break;
211
212    case SCMD_WEAPON_CHANGE :                          // change weapon
213    {
214      uint32_t new_weap;
215      if (pk.read((uint8_t *)&new_weap,4)!=4)
216        return 0;
217      else
218      {
219    f->current_weapon=lltl(new_weap);
220    f->suggest.send_weapon_change=0;
221    if (is_server)                      // if we are a server, tell everybody about this.
222    {
223      uint8_t cmd=SCMD_WEAPON_CHANGE;
224      next_out.write((uint8_t *)&cmd,1);
225      uint16_t pn=lstl(f->player_number);
226      next_out.write((uint8_t *)&pn,2);
227      next_out.write((uint8_t *)&new_weap,4);
228    }
229      }
230    } break;
231
232
233    case SCMD_SET_INPUT :                        // set the input from this player
234    {
235      signed char inp[5];
236      if (pk.read((uint8_t *)inp,5)!=5)
237        return 0;
238      else
239        f->set_input(inp[0],inp[1],inp[2],inp[3],inp[4]);
240    } break;
241
242    case SCMD_ADD_VIEW :
243    {
244      view *v=add_view(pk);
245      if (v)
246      {
247    for (view *f=player_list; f && f->next; f=f->next);
248    if (f) f->next=v;
249    else player_list=f;
250      }
251    } break;
252    case SCMD_SYNC :
253    {
254      uint32_t x;
255      if (pk.read((uint8_t *)&x,4)!=4)
256        return 0;
257      else
258      {
259    uint32_t s=make_sync_uint32();
260    if (lltl(x)!=s)
261      printf("Out of sync, %x!=%x\n",lltl(x),s);
262    return 1;
263      }
264    } break;
265
266    default :
267      return 0;
268  }
269  return 1;
270}
271
272void server::add_change_log(view *f, packet &pk, int number)
273{
274  if (f->view_changed())
275  {
276    uint8_t cmd=SCMD_VIEW_RESIZE;
277    pk.write(&cmd,1);
278    if (number)
279    {
280      uint16_t pn=lstl(f->player_number);
281      pk.write((uint8_t *)&pn,2);
282      dprintf("Server : %s resized view %d %d %d %d\n",f->name,
283          f->suggest.cx1,f->suggest.cy1,f->suggest.cx2,f->suggest.cy2);
284      f->resize_view(f->suggest.cx1,f->suggest.cy1,f->suggest.cx2,f->suggest.cy2);
285      f->suggest.send_view=0;
286    } else dprintf("sending resize to server\n");
287    uint32_t view_size[8];
288    view_size[0]=lltl(f->suggest.cx1);
289    view_size[1]=lltl(f->suggest.cy1);
290    view_size[2]=lltl(f->suggest.cx2);
291    view_size[3]=lltl(f->suggest.cy2);
292    view_size[4]=lltl(f->suggest.pan_x);
293    view_size[5]=lltl(f->suggest.pan_y);
294    view_size[6]=lltl(f->suggest.shift_down);
295    view_size[7]=lltl(f->suggest.shift_right);
296    pk.write((uint8_t *)view_size,8*4);
297  }
298
299  if (f->weapon_changed())
300  {
301    uint8_t cmd=SCMD_WEAPON_CHANGE;
302    pk.write(&cmd,1);
303    if (number)
304    {
305      uint16_t pn=lstl(f->player_number);
306      pk.write((uint8_t *)&pn,2);
307      dprintf("Server : %s change weapon to %d\n",f->name,f->suggest.new_weapon);
308      f->current_weapon=f->suggest.new_weapon;
309      f->suggest.send_weapon_change=0;
310    } else dprintf("sending resize to server\n");
311    uint32_t nw=lltl(f->suggest.new_weapon);
312    pk.write((uint8_t *)&nw,4);
313  }
314}
315
316int server::send_inputs(view *f)
317{
318  packet pk;
319  add_change_log(f,pk,0);
320  signed char inp[6];
321  inp[0]=SCMD_SET_INPUT;
322  inp[1]=f->x_suggestion;
323  inp[2]=f->y_suggestion;
324  inp[3]=f->b1_suggestion;
325  inp[4]=f->b2_suggestion;
326  inp[5]=f->b3_suggestion;
327  if (pk.write((uint8_t *)inp,6)!=6)
328    return 0;
329  if (!send_pkt(f->connect,pk))
330    return 0;
331  return 1;
332}
333
334
335void server::collect_inputs()
336{
337  out_socket *collect_server=NULL;
338  for (view *f=player_list; f; )
339  {
340    view *next=f->next;
341    if (is_server)
342    {
343      if (f->connect)
344      {
345    packet pk;
346    if (get_pkt(f->connect,pk))
347    {
348      while (!pk.eop())
349      {
350        uint8_t cmd;
351        if (pk.read((uint8_t *)&cmd,1)==1)
352          if (!process_command(f,cmd,pk))
353          { remove_player(f); f=NULL; }
354      }
355    } else
356    {
357      remove_player(f);
358      f=NULL;
359    }
360
361      } else
362      {
363        f->get_input();
364    add_change_log(f,next_out,1);
365      }
366    }
367    else
368    {
369      if (f->local_player())
370      {
371        f->get_input();
372    if (f->connect && !send_inputs(f))
373          remove_from_server(f);
374    else if (f->connect)
375          collect_server=f->connect;  // take note that we should collect the input back from the server
376      }
377    }
378    f=next;
379  }
380
381  if (collect_server)
382  {
383    packet pk;
384    if (!get_pkt(collect_server,pk))
385    {
386      for (view *f=player_list; f; f=f->next)
387        if (f->local_player())
388      remove_from_server(f);
389    }
390
391    if (!client_do_packet(pk))
392      printf("Error occurred while processing packet from server\n");
393  }
394
395  if (is_server && in)
396    distribute_changes();
397
398}
399
400
401void server::distribute_changes()
402{
403  char cmd;
404
405  for (view *f=player_list; f; f=f->next)
406  {
407    cmd=SCMD_SET_INPUT;
408    next_out.write((uint8_t *)&cmd,1);
409    uint16_t pn=lstl(f->player_number);
410    next_out.write((uint8_t *)&pn,2);
411
412    signed char inp[5];
413    inp[0]=f->x_suggestion;
414    inp[1]=f->y_suggestion;
415    inp[2]=f->b1_suggestion;
416    inp[3]=f->b2_suggestion;
417    inp[4]=f->b3_suggestion;
418    next_out.write((uint8_t *)inp,5);
419  }
420
421  if (sync_check)
422  {
423    cmd=SCMD_SYNC;
424    uint32_t x=lltl(make_sync_uint32());
425    next_out.write((uint8_t *)&cmd,1);
426    next_out.write((uint8_t *)&x,4);
427  }
428
429  for (f=player_list; f; )
430  {
431    view *n=f->next;
432    if (!f->local_player() && f->connect)
433      if (!send_pkt(f->connect,next_out))
434        remove_player(f);
435    f=n;
436  }
437
438}
439
440void server::check_for_new_players()
441{
442  if (is_server && has_net)
443  {
444    out_socket *nd=in->check_for_connect();
445    if (nd)
446    {
447      packet pk;
448//      pk.write_uint32(file_server->get_port());
449      if (!send_pkt(nd,pk))
450      {
451    printf("error writing to connection\n");
452    return ;
453      }
454
455//      while (!file_server->service_request()) milli_wait(1000);
456
457      if (!get_pkt(nd,pk))
458      {
459    printf("error reading from connection\n");
460    return ;
461      } else
462      {
463
464    char name[100];
465    pk.get_string(name,100);
466    printf("Joined by player %s\n",name);
467    pk.reset();
468    uint8_t ok=1;
469    pk.write((uint8_t *)&ok,1);      // write ok to join
470    send_pkt(nd,pk);
471
472    /**************** Read suggested view size from client ****/
473    if (!get_pkt(nd,pk))
474    {
475      printf("error reading view info from connection\n");
476      return ;
477    }
478    int32_t cx1,cy1,cx2,cy2;
479    if (pk.read((uint8_t *)&cx1,4)!=4) return ;  cx1=lltl(cx1);
480    if (pk.read((uint8_t *)&cy1,4)!=4) return ;  cy1=lltl(cy1);
481    if (pk.read((uint8_t *)&cx2,4)!=4) return ;  cx2=lltl(cx2);
482    if (pk.read((uint8_t *)&cy2,4)!=4) return ;  cy2=lltl(cy2);
483
484    /**************** Create the player  *******************/
485    for (view *f=player_list; f && f->next; f=f->next);      // find last player, add one for pn
486    int i,st=0;
487    for (i=0; i<total_objects; i++)
488      if (!strcmp(object_names[i],"START"))
489        st=i;
490
491    game_object *o=create(current_start_type,0,0);
492    game_object *start=current_level->get_random_start(320,NULL);
493    if (start) { o->x=start->x; o->y=start->y; }
494    else { o->x=100; o->y=100; }
495
496    f->next=new view(o,NULL,f->player_number+1);
497    o->set_controller(f->next);
498
499    current_level->add_object(o);
500    view *v=f->next;
501    v->cx1=cx1;
502    v->cy1=cy1;
503    v->cx2=cx2;
504    v->cy2=cy2;
505    v->connect=nd;
506    strcpy(v->name,name);
507
508
509    if (current_level->send(nd))
510    {
511      uint8_t cmd=SCMD_ADD_VIEW;
512      next_out.write((uint8_t *)&cmd,1);
513      v->write_packet(next_out);
514
515
516      /********** Send all of the views to the player **********/
517      pk.reset();
518      uint16_t tv=0;
519      for (f=player_list; f; f=f->next) tv++;
520      tv=lstl(tv);
521      pk.write((uint8_t *)&tv,2);
522      if (!send_pkt(nd,pk)) return ;
523
524      for (f=player_list; f; f=f->next)
525      {
526        pk.reset();
527        f->write_packet(pk);
528        if (!send_pkt(nd,pk)) return ;
529      }
530
531      pk.reset();
532      uint16_t r=lstl(rand_on);
533      pk.write((uint8_t *)&r,2);       // write current random seed
534      pk.write((uint8_t *)rtable,1024*2);
535      send_pkt(nd,pk);
536
537    }
538      }
539    }
540  }
541}
542
543
544
545
546int server::join_game(out_socket *os, char *name, char *server_name)
547{
548  char *re="Error occurred while reading from server\n";
549  packet pk;
550
551  if (!get_pkt(os,pk))                  // read join status packet, 0 means we can't join
552  { fputs(re,stderr); exit(0); }
553  int32_t nfs_port;
554  if (pk.read((uint8_t *)&nfs_port,4)!=4)
555  { fputs(re,stderr); exit(0); }
556
557//  connect_to_nfs_server(server_name,lltl(nfs_port));
558
559
560
561
562  pk.write((uint8_t *)name,strlen(name)+1);  // send or name and see if it's ok to join in
563  if (!send_pkt(os,pk))
564  {
565    printf("Unable to write to server\n");
566    exit(0);
567  }
568
569  if (!get_pkt(os,pk))                  // read join status packet, 0 means we can't join
570  { fputs(re,stderr); exit(0); }
571
572  uint8_t stat;
573  if (pk.read((uint8_t *)&stat,1)!=1)
574  { fputs(re,stderr); exit(0); }
575
576  if (stat==0)
577  {
578    printf("Sorry, this server is refusing you (%s)\n",name);
579    exit(0);
580  }
581
582
583  if (current_level)
584    delete current_level;
585
586  int32_t vs[4]={ lltl(320/2-155),lltl(200/2-95),lltl(320/2+155),lltl(200/2+70)};
587  pk.write((uint8_t *)vs,4*4);
588  if (!send_pkt(os,pk))   { printf("Unable to write to server\n"); exit(0);  }
589
590
591  current_level=new level(os);
592  if (current_level->load_failed())
593  {
594    printf("Error occurred while downloading level\n");
595    exit(1);
596  }
597
598  if (!get_pkt(os,pk))
599  {
600    printf("Unable to read views from server\n");
601    exit(0);
602  }
603  uint16_t tv;
604  if (pk.read((uint8_t *)&tv,2)!=2)
605  { fputs(re,stderr); exit(0); }
606  tv=lstl(tv);
607  view *last=NULL;
608  for (int i=0; i<tv; i++)
609  {
610    if (!get_pkt(os,pk)) { fputs(re,stderr); exit(0); }
611
612    view *v=add_view(pk);
613    if (v)
614    {
615      printf("added view %d\n",v->player_number);
616      if (last)
617        last->next=v;
618      else player_list=v;
619      last=v;
620    } else printf("no view created, why?\n");
621
622  }
623
624  if (!get_pkt(os,pk)) { fputs(re,stderr); exit(0); }
625  if (pk.read((uint8_t *)&rand_on,2)!=2)    // read the current random seed used by the server.
626  { fputs(re,stderr); exit(0); }
627  rand_on=lstl(rand_on);
628  uint16_t rtab[1024];
629  if (!pk.read((uint8_t *)rtab,1024*2)) { fputs(re,stderr); exit(0); }  // read the rand table
630
631  for (int j=0; j<1024*2; j++)
632    if (((uint8_t *)rtab)[j]!=((uint8_t *)rtable)[j])
633    { printf("rtables differ on byte %d\n",j); exit(0); }
634
635  if (last)
636  {
637    last->Drawable=1;
638    last->connect=os;
639  }
640
641  start_running=1;
642  is_server=0;
643  return 1;
644}
645
646
647
648
649
650
651void server::remove_player(view *f)
652{
653  uint8_t cmd=SCMD_REMOVE_VIEW;
654  next_out.write((uint8_t *)&cmd,1);
655  uint16_t pn=lstl(f->player_number);
656  next_out.write((uint8_t *)&pn,2);
657  if (f==player_list)
658    player_list=player_list->next;
659  else
660  {
661    for (view *v=player_list; v && v->next!=f; v=v->next);
662    v->next=f->next;
663  }
664
665  if (f->connect) delete f->connect;
666  f->focus->set_controller(NULL);
667  delete f;
668}
669
670
671/*int server::send_level(net_descriptor *os)
672{
673
674      cmd=SCMD_ADD_VIEW;
675      next_out.write((uint8_t *)&cmd,1);
676
677    uint16_t pn=lstl(new_player->player_number);
678    next_out.write((uint8_t *)&pn,2);
679    uint16_t type=lstlli(new_player->focus->otype);
680    next_out.write((uint8_t *)&type,2);
681    uint32_t x=lltl(new_player->focus->x),y=lltl(new_player->focus->y);
682    next_out.write((uint8_t *)&x,4);
683    next_out.write((uint8_t *)&y,4);
684  }*/
685
686
687
688#define TOT_VIEW_VARS 32
689view *server::add_view(packet &pk)
690{
691  uint32_t x[TOT_VIEW_VARS];
692  if (!pk.read((uint8_t *)x,TOT_VIEW_VARS*4)) return NULL;
693  for (int i=0; i<TOT_VIEW_VARS; i++) x[i]=lltl(x[i]);
694  int skip=0;
695  for (view *f=player_list; f; f=f->next)
696    if (f->player_number==x[0])
697      skip=1;
698
699  if (skip)
700  {
701    pk.advance(total_objects*4);
702    char nm[200];
703    pk.get_string(nm,100);
704    return NULL;
705  }
706  else
707  {
708    game_object *o=current_level->number_to_object(x[24]);
709    if (!o)
710    {
711      o=create(x[25],x[26],x[27]);
712      current_level->add_object(o);
713    }
714    view *v=new view(o,NULL,x[0]);
715    o->set_controller(v);
716
717    v->cx1=x[1];   v->cy1=x[2];   v->cx2=x[3];  v->cy2=x[4];
718    v->lives=x[5];
719    v->pan_x=x[6];       v->pan_y=x[7];
720    v->no_xleft=x[8];    v->no_xright=x[9];  v->no_ytop=x[10];  v->no_ybottom=x[11];
721    v->last_x=x[12];     v->last_y=x[13];
722    v->last_left=x[14];  v->last_right=x[15]; v->last_up=x[16]; v->last_down=x[17];
723    v->last_b1=x[18];    v->last_b2=x[19];    v->last_b3=x[20]; v->last_hp=x[21];
724    v->last_ammo=x[22];  v->last_type=x[23]; v->visor_time=x[28]; v->current_weapon=x[29];
725    v->secrets=x[30];    v->kills=x[31];
726
727    pk.read((uint8_t *)v->weapons,total_objects*4);
728    pk.get_string(v->name,100);
729
730
731    return v;
732  }
733}
734
735
736
737
738
739
740int server::client_do_packet(packet &pk)
741{
742  int rp=pk.get_read_position();
743
744  int er=0;
745  while (!pk.eop() && !er)
746  {
747    uint8_t cmd;
748    if (pk.read(&cmd,1)!=1)
749      er=1;
750    else
751    {
752      view *f=NULL;
753      int fail=0;
754      if (cmd!=SCMD_ADD_VIEW && cmd!=SCMD_SYNC)
755      {
756    uint16_t player;
757    if (pk.read((uint8_t *)&player,2)!=2)
758      er=1;
759    player=lstl(player);
760    for (f=player_list; f && f->player_number!=player; f=f->next);
761    if (!f) fail=1;
762      }
763      if (!fail)
764      {
765    if (!process_command(f,cmd,pk))
766      er=1;
767      }
768      else
769    er=1;
770    }
771  }
772  pk.set_read_position(rp);
773  return !er;
774}
775
776
777
778server::~server()
779{
780  if (in) delete in;
781}
782
783
Note: See TracBrowser for help on using the repository browser.