source: abuse/tags/0.7.0/src/old_server.cpp @ 43

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