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

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