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