source: abuse/trunk/src/netcfg.cpp @ 577

Last change on this file since 577 was 577, checked in by Sam Hocevar, 11 years ago

game: get rid of milli_wait() and rewrite the fixed framerate handling.

File size: 16.6 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 "common.h"
16
17#include "game.h"
18
19#include "netcfg.h"
20#include "input.h"
21#include "cache.h"
22#include "timing.h"
23#include "light.h"
24
25#include "dev.h"
26
27#if !defined __CELLOS_LV2__
28#   include "net/sock.h"
29#endif
30
31extern char *get_login();
32net_configuration *main_net_cfg = NULL;
33extern char lsf[256];
34
35#if !defined __CELLOS_LV2__
36extern net_protocol *prot;
37
38net_configuration::net_configuration()
39{
40  strcpy(name,get_login());
41
42  strcpy(server_name,"My Netgame");
43
44
45  min_players=2;
46  max_players=8;
47  kills=25;
48  port=20202;
49  server_port=20202;
50  state=SINGLE_PLAYER;
51}
52
53
54extern char game_name[50];
55
56enum { NET_OK=1, NET_CANCEL, NET_SERVER_NAME, NET_NAME, NET_PORT, NET_SERVER_PORT, NET_MAX, NET_MIN, NET_KILLS, CFG_ERR_OK, NET_SERVER,
57       NET_CLIENT, NET_SINGLE, NET_GAME=400,  MIN_1,MIN_2,MIN_3,MIN_4,MIN_5,MIN_6,MIN_7,MIN_8,   MAX_2,MAX_3,MAX_4,MAX_5,MAX_6,MAX_7,MAX_8,
58       LVL_2,LVL_4,LVL_8,LEVEL_BOX } ;
59
60
61void net_configuration::cfg_error(char const *msg)
62{
63  Jwindow *j=wm->new_window(-1,0,-1,-1,new info_field(0, 0, 0, msg,
64      new button(0, 30,CFG_ERR_OK,symbol_str("ok_button"),NULL)),symbol_str("input_error"));
65  event ev;
66  do
67  {
68    wm->flush_screen();
69    do { wm->get_event(ev); } while (ev.type==EV_MOUSE_MOVE && wm->event_waiting());
70  } while (ev.type!=EV_MESSAGE || ev.message.id!=CFG_ERR_OK || ev.type==EV_CLOSE_WINDOW || (ev.type==EV_KEY && ev.key==JK_ESC));
71  wm->close_window(j);
72  wm->flush_screen();
73}
74
75int net_configuration::restart_state()
76{
77  switch (state)
78  {
79    case RESTART_SERVER :
80    case RESTART_CLIENT :
81    case RESTART_SINGLE :
82      return 1;
83    default:
84      break;
85  }
86  return 0;
87}
88
89int net_configuration::notify_reset()
90{
91  switch (state)
92  {
93    case RESTART_SERVER : { state=SERVER; } break;
94    case RESTART_CLIENT : { state=CLIENT; } break;
95    case RESTART_SINGLE : { state=SINGLE_PLAYER; } break;
96    default: break;
97  }
98
99
100  return 1;
101}
102
103
104int net_configuration::confirm_inputs(InputManager *i, int server)
105{
106  if (server)
107  {
108    int kl;
109
110    if (sscanf(i->get(NET_KILLS)->read(),"%d",&kl)!=1 || kl<1 || kl>99)  {  error(symbol_str("kill_error")); return 0; }
111
112    char *nm=i->get(NET_NAME)->read();
113    if (strstr(nm,"\"")) {  error(symbol_str("name_error")); return 0; }
114    strcpy(name,nm);
115
116    min_players=((ifield *)(i->get(NET_MIN)->read()))->id-MIN_1+1;
117    max_players=((ifield *)(i->get(NET_MAX)->read()))->id-MAX_2+2;
118    if (max_players<min_players)  {  error(symbol_str("max_error")); return 0; }
119
120    char *s_nm=i->get(NET_SERVER_NAME)->read();
121    if (strstr(s_nm,"\"")) {  error(symbol_str("game_error")); return 0; }
122
123    strcpy(game_name,s_nm);
124
125    bFILE *fp=open_file("addon/deathmat/gamename.lsp","wb");
126    if (!fp->open_failure())
127    {
128      char str[100];
129      sprintf(str,"(setq gamename \"%s\")\n",game_name);
130      fp->write(str,strlen(str)+1);
131    }
132    delete fp;
133    strcpy(lsf,"addon/deathmat/deathmat.lsp");
134
135
136    fp=open_file("addon/deathmat/levelset.lsp","wb");
137    if (!fp->open_failure())
138    {
139      char str[100];
140      if (((ifield *)(i->get(LEVEL_BOX)->read()))->id==LVL_2)
141        sprintf(str,"(load \"addon/deathmat/small.lsp\")\n");
142      else if (((ifield *)(i->get(LEVEL_BOX)->read()))->id==LVL_4)
143        sprintf(str,"(load \"addon/deathmat/medium.lsp\")\n");
144      else
145        sprintf(str,"(load \"addon/deathmat/large.lsp\")\n");
146      fp->write(str,strlen(str)+1);
147    }
148    delete fp;
149
150
151    kills=kl;
152
153  } else  {
154    char *nm=i->get(NET_NAME)->read();
155    if (strstr(nm,"\"")) {  error(symbol_str("name_error")); return 0; }
156    strcpy(name,nm);
157  }
158
159  bFILE *fp=open_file("addon/deathmat/username.lsp","wb");
160  if (!fp->open_failure())
161  {
162    char str[100];
163    sprintf(str,"(setq username \"%s\")\n",name);
164    fp->write(str,strlen(str)+1);
165  }
166  delete fp;
167
168
169
170  return 1;
171
172}
173
174extern int start_running,demo_start,start_edit;
175
176/*int net_configuration::input()   // pulls up dialog box and input fileds
177{
178  ifield *ilist=NULL;
179  int x=0,y=0;
180
181  Jwindow *sv=wm->new_window(50,80,-1,-1,new button(0,0,NET_SERVER,symbol_str("server"),
182                     new button(0,wm->font()->height()*2,NET_CLIENT,symbol_str("client"),
183                     new button(0,wm->font()->height()*4,NET_SINGLE,symbol_str("single_play"),
184                     new button(0,wm->font()->height()*6,NET_CANCEL,symbol_str("cancel_net"),
185                        NULL)))),symbol_str("Networking"));
186
187  event ev;
188  int done=0;
189  do
190  {
191    wm->flush_screen();
192    do { wm->get_event(ev); } while (ev.type==EV_MOUSE_MOVE && wm->event_waiting());
193    if (ev.type==EV_MESSAGE)
194    {
195      if (ev.message.id==NET_SERVER) { done=1; state=RESTART_SERVER;  start_edit=0; demo_start=0; start_running=1; }
196      else if (ev.message.id==NET_CLIENT) { done=1; state=RESTART_CLIENT;  start_edit=0; demo_start=0; start_running=1; }
197      else if (ev.message.id==NET_SINGLE) { done=1; state=RESTART_SINGLE;  start_edit=0; demo_start=0; start_running=0; }
198      else if (ev.message.id==NET_CANCEL) { done=1; }
199    } else if (ev.type==EV_CLOSE_WINDOW || (ev.type==EV_KEY & ev.key==JK_ESC)) done=1;
200
201  } while (!done);
202
203  wm->close_window(sv);
204  wm->flush_screen();
205
206  if (state==RESTART_SINGLE)
207  {
208    strcpy(lsf,"abuse.lsp");
209    return 1;
210  }
211  if (ev.message.id==NET_CANCEL || state==RESTART_SINGLE) return 0;
212
213  if (state==RESTART_SERVER)
214  {
215    ilist=new button(x,y,NET_CANCEL,symbol_str("cancel_button"),ilist);
216    ilist=new button(x,y,NET_OK,       symbol_str("server"),ilist);
217    ilist=new text_field(x,y,NET_KILLS,symbol_str("kills_to_win"),"******",kills,ilist);
218    ilist=new text_field(x,y,NET_MAX,symbol_str("max_play"),"******",max_players,ilist);
219    ilist=new text_field(x,y,NET_MIN,symbol_str("min_play"),"******",min_players,ilist);
220    ilist=new text_field(x,y,NET_PORT,symbol_str("use_port"),"******",port,ilist);
221    ilist=new text_field(x,y,NET_NAME,symbol_str("your_name"),"****************",name,ilist);
222
223  } else
224  {
225    ilist=new button(x,y,NET_CANCEL,symbol_str("cancel_button"),ilist);
226    ilist=new button(x,y,NET_OK,symbol_str("client"),ilist);
227//    ilist=new text_field(x,y,NET_PORT,symbol_str("use_port"),"******",port,ilist);
228    ilist=new text_field(x,y,NET_SERVER_PORT,symbol_str("server_port"),"******",server_port,ilist);
229    ilist=new text_field(x,y,NET_SERVER_NAME,symbol_str("server_name"),"*********************************",game_name,ilist);
230    ilist=new text_field(x,y,NET_NAME,symbol_str("your_name"),"****************",name,ilist);
231  }
232
233  ifield *i=ilist;
234  for (; i; i=i->next)
235  {
236    i->y=y;
237    int x1,y1,x2,y2;
238    i->area(x1,y1,x2,y2);
239    y=y2+2;
240  }
241
242
243  Jwindow *nw=wm->new_window(0,0,-1,-1,ilist,symbol_str("Networking"));
244
245  done=0;
246  do
247  {
248    wm->flush_screen();
249    do { wm->get_event(ev); } while (ev.type==EV_MOUSE_MOVE && wm->event_waiting());
250    if (ev.type==EV_MESSAGE && ev.message.id==NET_OK && confirm_inputs(nw,state==RESTART_SERVER))
251      done=1;
252    if (ev.type==EV_MESSAGE && (ev.message.id==NET_CANCEL || ev.message.id==NET_SINGLE))
253       done=1;
254    if (ev.type==EV_CLOSE_WINDOW || (ev.type==EV_KEY && ev.key==JK_ESC))
255      done=1;
256
257  } while (!done);
258  wm->close_window(nw);
259  wm->flush_screen();
260
261  return ev.message.id==NET_OK;
262}
263
264*/
265
266
267void net_configuration::error(char const *message)
268{
269  image *screen_backup=screen->copy();
270
271  image *ns=cache.img(cache.reg("art/frame.spe","net_screen",SPEC_IMAGE,1));
272  int ns_w=ns->Size().x,ns_h=ns->Size().y;
273  int x=(xres+1)/2-ns_w/2,y=(yres+1)/2-ns_h/2;
274  ns->put_image(screen,x,y);
275  JCFont *fnt=wm->font();
276
277  uint8_t *remap=white_light+30*256;
278
279  uint8_t *sl=screen->scan_line(0);
280  int xx=screen->Size().x*screen->Size().y;
281  for (; xx; xx--,sl++) *sl=remap[*sl];
282
283  int fx=x+ns_w/2-strlen(message)*fnt->width()/2,
284    fy=y+ns_h/2-fnt->height();
285
286  fnt->put_string(screen,fx+1,fy+1,message,wm->black());
287  fnt->put_string(screen,fx,fy,message,wm->bright_color());
288
289
290  {
291    char const *ok = symbol_str("ok_button");
292
293    int bx=x+ns_w/2-strlen(ok)*fnt->width()/2-3,
294      by=y+ns_h/2+fnt->height()*3;
295
296    button *sb=new button(bx,by,NET_SERVER,ok,NULL);
297
298    InputManager inm(screen,sb);
299    inm.allow_no_selections();
300    inm.clear_current();
301
302    int done=0;
303    event ev;
304    do
305    {
306      wm->flush_screen();
307      do  { wm->get_event(ev); } while (ev.type==EV_MOUSE_MOVE && wm->event_waiting());
308      inm.handle_event(ev,NULL);
309      if ((ev.type==EV_KEY && (ev.key==JK_ESC || ev.key==JK_ENTER)) ||
310      ev.type==EV_MESSAGE) done=1;
311    } while (!done);
312  }
313
314  screen_backup->put_image(screen,0,0);
315  wm->flush_screen();
316  delete screen_backup;
317}
318
319
320ifield *net_configuration::center_ifield(ifield *i,int x1, int x2, ifield *place_below)
321{
322  int X1,Y1,X2,Y2;
323  i->area(X1,Y1,X2,Y2);
324  i->x=(x1+x2)/2-(X2-X1)/2;
325
326  if (place_below)
327  {
328    place_below->area(X1,Y1,X2,Y2);
329    i->y=Y2+2;
330  }
331  return i;
332}
333
334int net_configuration::get_options(int server)
335{
336  image *ns=cache.img(cache.reg("art/frame.spe","net_screen",SPEC_IMAGE,1));
337  int ns_w=ns->Size().x,ns_h=ns->Size().y;
338  int x=(xres+1)/2-ns_w/2,y=(yres+1)/2-ns_h/2;
339  ns->put_image(screen,x,y);
340  JCFont *fnt=wm->font();
341  image *ok_image=cache.img(cache.reg("art/frame.spe","dev_ok",SPEC_IMAGE,1))->copy(),
342    *cancel_image=cache.img(cache.reg("art/frame.spe","cancel",SPEC_IMAGE,1))->copy();
343
344  ifield *list=NULL;
345
346  if (server)
347  {
348    list=center_ifield(new text_field(x,y+30,NET_NAME,symbol_str("your_name"),"************************",name,list),x,x+ns_w,NULL);
349    list=center_ifield(new text_field(0,0,NET_SERVER_NAME,symbol_str("server_name"),"************************",game_name,list),x,x+ns_w,list);
350    list=center_ifield(new info_field(0,0,0,symbol_str("min_play"),list),x,x+ns_w,list);
351
352
353    button_box *b=new button_box(0,0,NET_MIN,1,NULL,list);
354    b->add_button(new button(0,0,MIN_8,"8",NULL));
355    b->add_button(new button(0,0,MIN_7,"7",NULL));
356    b->add_button(new button(0,0,MIN_6,"6",NULL));
357    b->add_button(new button(0,0,MIN_5,"5",NULL));
358    b->add_button(new button(0,0,MIN_4,"4",NULL));
359    b->add_button(new button(0,0,MIN_3,"3",NULL));
360    button *r=new button(0,0,MIN_2,"2",NULL); r->push();
361    b->add_button(r);
362    b->add_button(new button(0,0,MIN_1,"1",NULL));
363
364
365
366    b->arrange_left_right();
367    center_ifield(b,x,x+ns_w,list);
368    b->arrange_left_right();
369    list=b;
370
371    list=center_ifield(new info_field(0,0,0,symbol_str("max_play"),list),x,x+ns_w,list);
372
373    b=new button_box(0,0,NET_MAX,1,NULL,list);
374    button *q=new button(0,0,MAX_8,"8",NULL); q->push();
375    b->add_button(q);
376    b->add_button(new button(0,0,MAX_7,"7",NULL));
377    b->add_button(new button(0,0,MAX_6,"6",NULL));
378    b->add_button(new button(0,0,MAX_5,"5",NULL));
379    b->add_button(new button(0,0,MAX_4,"4",NULL));
380    b->add_button(new button(0,0,MAX_3,"3",NULL));
381    b->add_button(new button(0,0,MAX_2,"2",NULL));
382    b->arrange_left_right();
383    center_ifield(b,x,x+ns_w,list);
384    b->arrange_left_right();
385    list=b;
386
387
388    list=center_ifield(new info_field(0,0,0,symbol_str("level_size"),list),x,x+ns_w,list);
389
390    b=new button_box(0,0,LEVEL_BOX,1,NULL,list);
391    b->add_button(new button(0,0,LVL_8,symbol_str("lvl_8"),NULL));
392    b->add_button(new button(0,0,LVL_4,symbol_str("lvl_4"),NULL));
393    q=new button(0,0,LVL_2,symbol_str("lvl_2"),NULL); q->push();
394    b->add_button(q);
395
396    b->arrange_left_right();
397    center_ifield(b,x,x+ns_w,list);
398    b->arrange_left_right();
399    list=b;
400
401    list=center_ifield(new text_field(0,0,NET_KILLS,symbol_str("kills_to_win"),"***","25",list),x,x+ns_w,list);
402
403
404
405
406  } else
407  {
408    list=center_ifield(new text_field(x,y+80,NET_NAME,symbol_str("your_name"),"************************",name,list),x,x+ns_w,NULL);
409  }
410
411
412  list=new button(x+80-17,y+ns_h-20-fnt->height(),NET_OK,ok_image,list);
413  list=new button(x+80+17,y+ns_h-20-fnt->height(),NET_CANCEL,cancel_image,list);
414
415  int ret=0;
416
417  {
418    InputManager inm(screen,list);
419    inm.allow_no_selections();
420    inm.clear_current();
421
422    int done=0;
423    event ev;
424    do
425    {
426      wm->flush_screen();
427      do { wm->get_event(ev); } while (ev.type==EV_MOUSE_MOVE && wm->event_waiting());
428      inm.handle_event(ev,NULL);
429      if (ev.type==EV_MESSAGE)
430      {
431    switch (ev.message.id)
432    {
433      case NET_OK : { if (confirm_inputs(&inm,server))
434          { ret=1; done=1; }
435          else { ((button *)inm.get(NET_OK))->push(); inm.redraw(); }
436          } break;
437      case NET_CANCEL : done=1;
438    }
439      } if (ev.type==EV_KEY && ev.key==JK_ESC) done=1;
440
441    } while (!done);
442
443  }
444  delete ok_image;
445  delete cancel_image;
446
447  return ret;
448}
449
450int net_configuration::input()   // pulls up dialog box and input fileds
451{
452  int ret=0;
453  screen->clear();
454
455  image *ns=cache.img(cache.reg("art/frame.spe","net_screen",SPEC_IMAGE,1));
456  int ns_w=ns->Size().x,ns_h=ns->Size().y;
457  int x=(xres+1)/2-ns_w/2,y=(yres+1)/2-ns_h/2;
458  ns->put_image(screen,x,y);
459  char const *nw_s = symbol_str("Networking");
460  JCFont *fnt=wm->font();
461
462
463  wm->font()->put_string(screen,x+ns_w/2-strlen(nw_s)*fnt->width()/2,y+21/2-fnt->height()/2,
464      nw_s,wm->medium_color());
465  {
466
467    char const *server_str = symbol_str("server");
468    button *sb=new button(x+40,y+ns_h-23-fnt->height(),NET_SERVER,server_str,NULL);
469
470    if (main_net_cfg && (main_net_cfg->state==CLIENT || main_net_cfg->state==SERVER))
471      sb=new button(x+40,y+ns_h-9-fnt->height(),NET_SINGLE,symbol_str("single_play"),sb);
472
473    InputManager inm(screen,sb);
474
475    inm.allow_no_selections();
476    inm.clear_current();
477
478
479    event ev;
480    int done=0;
481    int button_y=25,total_games=0;
482    enum { MAX_GAMES=9 };
483    net_address *game_addr[MAX_GAMES+1];
484    int join_game=-1;
485    time_marker start,now;
486
487    do
488    {
489      if (wm->event_waiting())
490      {
491        do  { wm->get_event(ev); } while (ev.type==EV_MOUSE_MOVE && wm->event_waiting());
492        inm.handle_event(ev,NULL);
493        if (ev.type==EV_MESSAGE)
494        {
495          switch (ev.message.id)
496          {
497            case NET_CANCEL : done=1; break;
498            case NET_SERVER : done=1; break;
499            case NET_SINGLE : done=1; break;
500            default :
501              if (ev.message.id>=NET_GAME && ev.message.id<NET_GAME+MAX_GAMES)
502              {
503                join_game=ev.message.id-NET_GAME;
504                done=1;
505              }
506          }
507        }
508        else if (ev.type==EV_KEY && ev.key==JK_ESC )
509        {
510            done=1;
511        }
512        else
513        {
514            // No event waiting...  We can't wait for long, because we are
515            // pretending to broadcast.
516            // ECS - Added so waiting in dialog doesn't use 100% of CPU
517            Timer tmp; tmp.WaitMs(5);
518        }
519    }
520
521      wm->flush_screen();
522      char name[256];
523
524      now.get_time();
525      if (total_games<MAX_GAMES && now.diff_time(&start)>0.5)
526      {
527        start.get_time();
528        net_address *find=prot->find_address(0x9090,name);    // was server_port
529        if (find)
530        {
531          int bw=strlen(name)*fnt->width();
532          inm.add(new button(x+ns_w/2-bw/2,y+button_y,NET_GAME+total_games,name,NULL));
533          find->set_port(server_port);
534          game_addr[total_games]=find;
535
536          total_games++;
537          button_y+=fnt->height()+10;
538          inm.redraw();
539        }
540      }
541
542    } while (!done);
543
544    prot->reset_find_list();
545
546    if (join_game>=0)
547    {
548      if (get_options(0))
549      {
550        int still_there=1;  // change this back to 0, to check if games are stil alive
551        time_marker start,now;
552        do
553        {
554          now.get_time();
555          char name[256];
556          net_address *find=prot->find_address(0x9090,name);  // was server_port
557          if (find)
558          {
559            if (find->equal(game_addr[join_game]))
560              still_there=1;
561            delete find;
562          }
563
564        } while (now.diff_time(&start)<3 && !still_there);
565
566        if (still_there)
567        {
568          game_addr[join_game]->store_string(server_name,sizeof(server_name));
569          state=RESTART_CLIENT;
570          ret=1;
571
572        } else error(symbol_str("not_there"));
573
574
575        prot->reset_find_list();
576        int i;
577        for (i=0; i<total_games; i++)        // delete all the addresses we found and stored
578          delete game_addr[join_game];
579      }
580    } else if (ev.type==EV_MESSAGE && ev.message.id==NET_SERVER)
581    {
582      if (get_options(1))
583      {
584        state=RESTART_SERVER;
585        return 1;
586      }
587      else return 0;
588    } else if (ev.type==EV_MESSAGE && ev.message.id==NET_SINGLE)
589    {
590      state=RESTART_SINGLE;
591      start_running=0;
592
593      strcpy(lsf,"abuse.lsp");
594      return 1;
595    }
596  }
597
598  return ret;
599}
600
601#endif // __CELLOS_LV2__
602
Note: See TracBrowser for help on using the repository browser.