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

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

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