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

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