source: abuse/branches/lol/src/old_server.cpp @ 732

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

build: SDL2 compilation fixes.

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