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