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 
31 extern char *get_login();
32 net_configuration *main_net_cfg = NULL;
33 extern char lsf[256];
34 
35 #if !defined __CELLOS_LV2__
36 extern net_protocol *prot;
37 
net_configuration()38 net_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 
54 extern char game_name[50];
55 
56 enum { 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 
cfg_error(char const * msg)61 void 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 
restart_state()75 int 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 
notify_reset()89 int 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 
confirm_inputs(InputManager * i,int server)104 int 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 
174 extern 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 
error(char const * message)267 void 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 
center_ifield(ifield * i,int x1,int x2,ifield * place_below)320 ifield *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 
get_options(int server)334 int 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 
input()450 int 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 
603