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

Last change on this file since 650 was 650, checked in by Sam Hocevar, 9 years ago

imlib: make some Image methods use vec2i.

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