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

Last change on this file since 490 was 490, checked in by Sam Hocevar, 10 years ago

lisp: implement LispList::GetLength?.

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