1 #ifndef WIN32
2 #include "config.h"
3 #endif
4 
5 #include <stdio.h>
6 #include <sys/types.h>
7 
8 #if (!defined(WIN32))
9 	#ifdef TIME_WITH_SYS_TIME
10 		#include <sys/time.h>
11 		#include <time.h>
12 	#else
13 		#ifdef TM_IN_SYS_TIME
14 			#include <sys/time.h>
15 		#else
16 			#include <time.h>
17 		#endif
18 	#endif
19 	#include <sys/socket.h>
20 #else
21 	#include <time.h>
22 	#include <winsock.h>
23 #endif
24 
25 #include <stdlib.h>
26 #include <signal.h>
27 #include <math.h>
28 #include <errno.h>
29 #ifdef HAVE_FLOAT_H
30 #include <float.h>
31 #endif
32 #ifndef __USE_GNU
33 	#define __USE_GNU
34 #endif
35 #include <string.h>
36 
37 #ifdef HAVE_SYS_SELECT_H
38 #include <sys/select.h>
39 #endif
40 
41 #ifdef __EMX__
42 #define INCL_DOS
43 #include <os2.h>
44 #endif
45 
46 #include "data.h"
47 #include "server.h"
48 #include "net.h"
49 #include "cfg.h"
50 #include "hash.h"
51 #include "time.h"
52 #include "getopt.h"
53 #include "math.h"
54 #include "error.h"
55 
56 
57 unsigned short port=DEFAULT_PORT;  /* game port (not a gameport ;-) )*/
58 int level_number=0;   /* line number in the LEVEL_FILE */
59 int fd;   /* socket */
60 int n_players;   /* highest ID of player */
61 int active_players=0;  /* # of players in the game */
62 unsigned int id=0;  /* my ID */
63 unsigned long_long game_start; /* time of game start */
64 /* important sprites */
65 int grenade_sprite,bullet_sprite,slug_sprite,shell_sprite,shotgun_shell_sprite,mess1_sprite,mess2_sprite,mess3_sprite,mess4_sprite,noise_sprite;
66 int shrapnel_sprite[N_SHRAPNELS];
67 int nonquitable=0;  /* 1=clients can't abort game pressing F12 (request is ignored) */
68 unsigned long_long last_tick;
69 unsigned long_long last_player_left=0,last_packet_came=0;
70 
71 unsigned char *level_checksum=0;   /* MD5 sum of the level */
72 
73 unsigned char weapons_order[ARMS]={4,0,3,1,2};
74 
75 struct birthplace_type
76 {
77 	int x,y;
78 }*birthplace=DUMMY;
79 
80 int n_birthplaces=0;
81 
82 /* list of players */
83 struct player_list
84 {
85         struct player_list *next,*prev;
86         struct player member;
87 }players;
88 
89 
90 /* time queue of respawning objects */
91 struct queue_list
92 {
93 	struct queue_list* next;
94 	unsigned long_long time;
95 	struct it member;
96 }time_queue;
97 
98 
99 /* list of objects */
100 struct object_list objects;
101 
102 struct player_list *last_player;
103 struct object_list *last_obj;
104 
105 
106 #ifdef WIN32
107 	#define random rand
108 	#define srandom srand
109 
110 	#define	SERVICE_NAME			"0verkill_015"
111 	#define	SERVICE_DISP_NAME		"0verkill Server 0.15"
112 	int		consoleApp=0;	/* 0 kdyz to bezi jako server na pozadi */
113 
114 /***************************************************/
115 /* WINDOWS NT SERVICE INSTALLATION/RUNNING/REMOVAL */
116 
117 #include <winsvc.h>
118 
119 int server(void);
120 
121 SERVICE_STATUS			ssStatus;
122 SERVICE_STATUS_HANDLE	sshStatusHandle;
123 DWORD					globErr=ERROR_SUCCESS;
124 TCHAR					szErr[2048];
125 int						hServerExitEvent=0;	/* close server flag */
126 
GetLastErrorText(LPTSTR lpszBuf,DWORD dwSize)127 LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize) {
128 	DWORD	dwRet;
129 	LPTSTR	lpszTemp=NULL;
130 	globErr=GetLastError();
131 	dwRet=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL,
132 		globErr, LANG_NEUTRAL, (LPTSTR)&lpszTemp, 0, NULL);
133 	/* supplied buffer is not long enough */
134 	if (( !dwRet )||( (long)dwSize < (long)dwRet+14 ))
135 		sprintf(lpszBuf, ": %u", globErr);
136 	else {
137 		lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0');
138 		CharToOem(lpszTemp, lpszTemp);
139 		sprintf(lpszBuf, ": %u: %s", globErr, lpszTemp);
140 	}
141 	if ( lpszTemp )
142 		LocalFree((HLOCAL)lpszTemp);
143 	return lpszBuf;
144 }
145 
CmdInstallService(LPCTSTR pszUserName,LPCTSTR pszUserPassword,LPCTSTR pszDependencies)146 void CmdInstallService(LPCTSTR pszUserName, LPCTSTR pszUserPassword, LPCTSTR pszDependencies) {
147 	SC_HANDLE   schService;
148 	SC_HANDLE   schSCManager;
149 	TCHAR		szPath[2048];
150 	printf("Installing %s as ", SERVICE_NAME);
151 	if ( pszUserName==NULL )
152 		printf("LOCAL_SYSTEM");
153 	else {
154 		printf("\"%s\"", pszUserName);
155 		if ( pszUserPassword )
156 			printf("/\"%s\"", pszUserPassword);
157 	};
158 	printf("...\r\n");
159 	if ( GetModuleFileName(NULL, szPath, 2046)==0 ) {
160 		printf("Unable to install %s%s\r\n", SERVICE_NAME, GetLastErrorText(szErr, 2046));
161 		return;
162 	};
163 	schSCManager=OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
164 	if ( schSCManager ) {
165 		schService=CreateService(
166 			schSCManager,               /* SCManager database */
167 			SERVICE_NAME,               /* name of service */
168 			SERVICE_DISP_NAME,          /* name to display */
169 			SERVICE_ALL_ACCESS,         /* desired access */
170 			SERVICE_WIN32_OWN_PROCESS,  /* service type */
171 			SERVICE_DEMAND_START,       /* start type */
172 			SERVICE_ERROR_NORMAL,       /* error control type */
173 			szPath,                     /* service's binary */
174 			NULL,                       /* no load ordering group */
175 			NULL,                       /* no tag identifier */
176 			pszDependencies,            /* dependencies */
177 			pszUserName,                /* account */
178 			pszUserPassword);           /* password */
179 		if ( schService ) {
180 			printf("%s was installed successfully.\r\n", SERVICE_NAME);
181 			globErr=ERROR_SUCCESS;
182 			CloseServiceHandle(schService);
183 		}
184 		else
185 			printf("CreateService failed%s\r\n", GetLastErrorText(szErr, 2046));
186 		CloseServiceHandle(schSCManager);
187 	}
188 	else
189 		printf("OpenSCManager failed%s\r\n", GetLastErrorText(szErr, 2046));
190 }
191 
CmdRemoveService()192 void CmdRemoveService() {
193 	SC_HANDLE	schService,
194 				schSCManager;
195 	schSCManager=OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
196 	if ( schSCManager ) {
197 		schService=OpenService(schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);
198 		if ( schService ) {
199 			if ( ControlService(schService, SERVICE_CONTROL_STOP, &ssStatus) ) {
200 				printf("Stopping %s...\r\n", SERVICE_NAME);
201 				Sleep(500);
202 				while( QueryServiceStatus(schService, &ssStatus) ) {
203 					if ( ssStatus.dwCurrentState==SERVICE_STOP_PENDING ) {
204 						printf(".");
205 						Sleep(500);
206 					}
207 					else
208 						break;
209 				};
210 				if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
211 					printf("\r\n%s stopped successfully.\r\n", SERVICE_NAME);
212 				else
213 					printf("\r\n%s failed to stop.\r\n", SERVICE_NAME);
214 			}
215 			else
216 				printf("ControlService failed%s\r\n", GetLastErrorText(szErr, 2046));
217 			if ( DeleteService(schService) ) {
218 				globErr=ERROR_SUCCESS;
219 				printf("%s removed.\r\n", SERVICE_NAME);
220 			}
221 			else
222 				printf("DeleteService failed%s\r\n", GetLastErrorText(szErr, 2046));
223 			CloseServiceHandle(schService);
224 		}
225 		else
226 			printf("OpenService failed%s\r\n", GetLastErrorText(szErr, 2046));
227 		CloseServiceHandle(schSCManager);
228 	}
229 	else
230 		printf("OpenSCManager failed%s\r\n", GetLastErrorText(szErr, 2046));
231 }
232 
AddToMessageLog(LPTSTR lpszMsg,int infoOnly)233 void AddToMessageLog(LPTSTR lpszMsg, int infoOnly) {
234 	TCHAR	szMsg[2048];
235 	HANDLE	hEventSource;
236 	LPTSTR	lpszStrings[2];
237 
238 	hEventSource=RegisterEventSource(NULL, SERVICE_NAME);
239 
240 	sprintf(szMsg, infoOnly ? "%s notification:" : "%s error: %u", SERVICE_NAME, globErr);
241 	lpszStrings[0]=szMsg;
242 	lpszStrings[1]=lpszMsg;
243 
244 	if ( hEventSource!=INVALID_HANDLE_VALUE ) {
245 		ReportEvent(hEventSource, infoOnly ? EVENTLOG_INFORMATION_TYPE : EVENTLOG_ERROR_TYPE, 0, 0, NULL, 2, 0, (LPCTSTR*)lpszStrings, NULL);
246 		DeregisterEventSource(hEventSource);
247 	};
248 };
249 
ReportStatusToSCMgr(DWORD dwCurrentState,DWORD dwWin32ExitCode,DWORD dwWaitHint)250 BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) {
251 	static DWORD	dwCheckPoint=1;
252     BOOL			fResult=TRUE;
253 
254 	if ( dwCurrentState==SERVICE_START_PENDING )
255 		ssStatus.dwControlsAccepted=0;
256 	else
257 		ssStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
258 
259 	ssStatus.dwCurrentState=dwCurrentState;
260 	ssStatus.dwWin32ExitCode=dwWin32ExitCode;
261 	ssStatus.dwWaitHint=dwWaitHint;
262 
263 	if (( dwCurrentState==SERVICE_RUNNING )||
264 		( dwCurrentState==SERVICE_STOPPED ))
265 		ssStatus.dwCheckPoint=0;
266 	else
267 		ssStatus.dwCheckPoint=dwCheckPoint++;
268 	if ( !(fResult=SetServiceStatus(sshStatusHandle, &ssStatus)) ) {
269 		globErr=GetLastError();
270 		AddToMessageLog("SetServiceStatus failed", 0);
271 	}
272 	return fResult;
273 }
274 
ServiceStop()275 void ServiceStop() {
276 	hServerExitEvent=1;
277 	raise(SIGINT);
278 }
279 
ServiceCtrl(DWORD dwCtrlCode)280 void WINAPI ServiceCtrl(DWORD dwCtrlCode) {
281 	switch( dwCtrlCode ) {
282 	case SERVICE_CONTROL_STOP:
283 		ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 500);
284 		ServiceStop();
285 		return;
286 	};
287 	if ( hServerExitEvent )
288 		ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
289 	else
290 		ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0);
291 }
292 
293 
ServiceStart(DWORD dwArgc,LPTSTR * lpszArgv)294 void ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv) {
295 	if ( dwArgc>1 )
296 		SetCurrentDirectory(lpszArgv[1]);
297 	else {
298 		char	path[1024],
299 				*p2;
300 		GetModuleFileName(NULL, path, sizeof(path));
301 		p2=path+strlen(path);
302 		while(( p2>=path )&&( *p2!='\\' )&&( *p2!='/' ))
303 			p2--;
304 		*p2=0;
305 		SetCurrentDirectory(path);
306 	}
307 	server();
308 }
309 
ServiceMain(DWORD dwArgc,LPTSTR * lpszArgv)310 void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
311 	if ( !(sshStatusHandle=RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrl)) )
312 		return;
313 
314 	ssStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
315 	ssStatus.dwServiceSpecificExitCode=0;
316 	if ( !ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 3000))
317 		goto Cleanup;
318 
319 	nonquitable=1;
320   	ServiceStart(dwArgc, lpszArgv);
321 
322 Cleanup:
323 	ReportStatusToSCMgr(SERVICE_STOPPED, globErr, 0);
324 	return;
325 };
326 /* WINDOWS NT SERVICE INSTALLATION/REMOVAL */
327 /*******************************************/
328 #endif
329 
330 
331 /* load dynamic data */
load_dynamic(unsigned char * filename)332 void load_dynamic(unsigned char * filename)
333 {
334 	FILE * stream;
335 	static unsigned char line[1024];
336 	char *p,*q,*name;
337 	int n,x,y,t;
338 
339 	if (!(stream=fopen(filename,"rb"))){unsigned char msg[256];snprintf(msg,256,"Can't open file \"%s\"!\n",filename);ERROR(msg);EXIT(1);}
340 	while(fgets(line,1024,stream))
341 	{
342 		p=line;
343 		_skip_ws(&p);
344 		for (name=p;(*p)!=' '&&(*p)!=9&&(*p)!=10&&(*p);p++);
345 		if (!(*p))continue;
346 		*p=0;p++;
347 		_skip_ws(&p);
348 		if ((t=_convert_type(*p))<0){unsigned char msg[256];snprintf(msg,256,"Unknown object type '%c'.\n",*p);ERROR(msg);EXIT(1);}
349 		p++;
350 		_skip_ws(&p);
351 		x=strtol(p,&q,0);
352 		_skip_ws(&q);
353 		y=strtol(q,&p,0);
354 		if (t==TYPE_BIRTHPLACE)   /* birthplace */
355 		{
356 			n_birthplaces++;
357 			birthplace=mem_realloc(birthplace,sizeof(struct birthplace_type)*n_birthplaces);
358 			if (!birthplace){ERROR("Error: Not enough memory.\n");EXIT(1);}
359 			birthplace[n_birthplaces-1].x=x;
360 			birthplace[n_birthplaces-1].y=y;
361 			continue;
362 		}
363 		if (find_sprite(name,&n)){unsigned char msg[256];snprintf(msg,256,"Unknown bitmap name \"%s\"!\n",name);ERROR(msg);EXIT(1);}
364 		new_obj(id,t,0,n,0,0,int2double(x),int2double(y),0,0,0);
365 		id++;
366 	}
367 	fclose(stream);
368 	if (!n_birthplaces){ERROR("Error: No birthplaces.\n");EXIT(1);}
369 }
370 
371 
print_ip(unsigned char * txt,struct in_addr ip)372 void print_ip(unsigned char * txt,struct in_addr ip)
373 {
374 	unsigned int a;
375 
376 	sprintf(txt,"%d",*((unsigned char *)&ip));
377 	for (a=1;a<sizeof(ip);a++)
378 		sprintf(txt+strlen(txt),".%d",((unsigned char *)&ip)[a]);
379 }
380 
381 
382 /* write a message to stdout or stderr */
message(unsigned char * msg,int output)383 void message(unsigned char *msg,int output)
384 {
385 	time_t t;
386 	struct tm tm;
387 	static unsigned char timestamp[64];
388 
389 #ifdef WIN32
390 	if ( !consoleApp )
391 		return;
392 #endif
393 
394 	t=time(0);
395 	tm=*(localtime(&t));
396 
397 	/* time stamp is in format day.month.year hour:minute:second */
398 	snprintf(timestamp,64,"%2d.%2d.%d %02d:%02d:%02d  ",tm.tm_mday,tm.tm_mon+1,tm.tm_year+1900,tm.tm_hour,tm.tm_min,tm.tm_sec);
399 	switch (output)
400 	{
401 		case 1:
402 		printf("%s%s",timestamp,msg);
403 		fflush(stdout);
404 		break;
405 
406 		case 2:
407 		fprintf(stderr,"%s%s",timestamp,msg);
408 		fflush(stderr);
409 		break;
410 	}
411 }
412 
413 
414 /* switch weapon to the player's best one */
select_best_weapon(struct player * p)415 int select_best_weapon(struct player* p)
416 {
417 	unsigned char t[ARMS]={4,0,1,3,2};
418 	int a;
419 
420 	for (a=ARMS-1;a>=0;a--)
421 		if ((p->weapons&(1<<t[a]))&&p->ammo[t[a]])return t[a];
422 
423 	return p->current_weapon;
424 }
425 
426 
427 /* Bakta modify - better weapon selection routines */
428 /* test if weapon is better than the one he wields */
is_weapon_better(struct player * p,int weapon)429 int is_weapon_better(struct player* p, int weapon)
430 {
431 	int i;
432 	int cur=0, test=0;
433 
434 	for(i=ARMS-1;i>=0;i--)
435 	{
436 		if(weapons_order[i]==p->current_weapon)
437 			cur = i;
438 		if(weapons_order[i]==weapon)
439 			test = i;
440 	}
441 	return cur<test;
442 }
443 
444 
445 /* test if player p has weapon and can use it (has ammo for it) */
is_weapon_usable(struct player * p,int weapon)446 int is_weapon_usable(struct player* p, int weapon)
447 {
448 	return !!((p->weapons&(1<<weapon))&&p->ammo[weapon]);
449 }
450 
451 
452 /* test if player p has weapon and has no ammo for it */
is_weapon_empty(struct player * p,int weapon)453 int is_weapon_empty(struct player* p, int weapon)
454 {
455 	return !!((p->weapons&(1<<weapon))&&!p->ammo[weapon]);
456 }
457 
458 
459 /* initialize socket */
init_socket(void)460 void init_socket(void)
461 {
462 	struct sockaddr_in server;
463 	fd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
464 	if (fd<0)
465 	{
466 		ERROR("Error: Can't create socket!\n");
467 		EXIT(1);
468 	}
469 
470 	server.sin_family=AF_INET;
471 	server.sin_port=htons(port);
472 	server.sin_addr.s_addr=INADDR_ANY;
473 
474 	if (bind(fd,(struct sockaddr*)&server,sizeof(server)))
475 	{
476 		unsigned char msg[256];
477 		snprintf(msg,256,"Error: Can't bind socket to port %d!\n",port);
478 		ERROR(msg);
479 		EXIT(1);
480 	}
481 }
482 
483 
484 /* selects random birthplace and returns */
find_birthplace(int * x,int * y)485 void find_birthplace(int *x,int *y)
486 {
487 	int a=random()%n_birthplaces;
488 
489 	*x=birthplace[a].x;
490 	*y=birthplace[a].y;
491 }
492 
493 
494 /* return index of hero with color num in sprites field */
495 /* if there's not such color, returns -1 */
select_hero(int num)496 int select_hero(int num)
497 {
498 	static unsigned char txt[32];
499 	int a;
500 
501 	sprintf(txt,"hero%d",num);
502 	if (find_sprite(txt,&a))return -1;
503 	return a;
504 }
505 
506 
507 /* initialize player */
init_player(struct player * p,my_double x,my_double y)508 void init_player(struct player* p,my_double x,my_double y)
509 {
510 	int a;
511 
512 	p->health=100;
513 	p->armor=0;
514 	p->current_weapon=0;
515 	p->weapons=17; /* he has only gun and grenades */
516 	p->invisibility_counter=0;
517 	for (a=0;a<ARMS;a++)
518 		p->ammo[a]=0;
519 	p->ammo[0]=weapon[0].basic_ammo;
520 	p->obj->xspeed=0;
521 	p->obj->yspeed=0;
522 	p->obj->status=0;
523 	p->obj->ttl=0;
524 	p->obj->anim_pos=0;
525 	p->obj->x=x;
526 	p->obj->y=y;
527 }
528 
529 
530 /* completely add player to server's database */
531 /* player starts on x,y coordinates */
add_player(unsigned char color,unsigned char * name,struct sockaddr_in * address,int x,int y)532 int add_player(unsigned char color, unsigned char *name,struct sockaddr_in *address,int x, int y)
533 {
534 	int h;
535 #define cp last_player->next
536 
537 	cp=last_player->next;
538 
539 	/* alloc memory for new player */
540 	cp=mem_alloc(sizeof(struct player_list));
541 	if (!cp)
542 		{message("Not enough memory.\n",2);return 1;}
543 	cp->member.name=mem_alloc(strlen(name)+1);
544 	if (!cp->member.name)
545 		{mem_free(cp);message("Not enough memory.\n",2);return 1;}
546 
547 	/* fill in the structure */
548 	cp->member.color=color;
549 	cp->member.frags=0;
550 	cp->member.deaths=0;
551 	cp->member.keyboard_status.left=0;
552 	cp->member.keyboard_status.right=0;
553 	cp->member.keyboard_status.speed=0;
554 	cp->member.keyboard_status.fire=0;
555 	cp->member.keyboard_status.creep=0;
556 	cp->member.keyboard_status.down_ladder=0;
557 	cp->member.keyboard_status.weapon=0;
558 	cp->member.id=n_players+1;  /* player numbering starts from 1, 0 is server's ID */
559 	cp->member.last_update=get_time();
560 	memcpy(cp->member.name,name,strlen(name)+1);
561 	cp->member.address=*address;
562 	cp->member.packet_pos=0;
563 	cp->member.current_level=-1;
564 	/* create new object "player" */
565 	h=select_hero(cp->member.color);
566 	if (h<0)
567 		{mem_free(cp->member.name);mem_free(cp);message ("No such color.\n",1);return 1;}
568 	cp->member.obj=new_obj(id,T_PLAYER,0,h,0,0,int2double(x),int2double(y),0,0,(&(cp->member)));
569 	if (!cp->member.obj)
570 		{mem_free(cp->member.name);mem_free(cp);message("Can't create object.\n",1);return 1;}
571 	id++;
572 	init_player(&(cp->member),int2double(x),int2double(y));
573 
574 	/* that's all */
575 	cp->prev=last_player;
576 	cp->next=0;
577 	last_player=cp;
578 #undef cp
579 	return 0;
580 }
581 
582 
send_chunk_to_player(struct player * player)583 void send_chunk_to_player(struct player *player)
584 {
585 	static unsigned char p[MAX_PACKET_LENGTH];
586 
587 	if (!(player->packet_pos))return;
588 	if (player->packet_pos>MAX_PACKET_LENGTH-1)return;
589 	p[0]=P_CHUNK;
590 	memcpy(p+1,player->packet,player->packet_pos);
591 	send_packet(p,(player->packet_pos)+1,(struct sockaddr*)(&(player->address)),0,player->id);
592 	player->packet_pos=0;
593 }
594 
595 
send_chunk_packet_to_player(unsigned char * packet,int len,struct player * player)596 void send_chunk_packet_to_player(unsigned char *packet, int len, struct player *player)
597 {
598 	if (len>MAX_PACKET_LENGTH-1)return;
599 	if ((player->packet_pos)+len>MAX_PACKET_LENGTH-1)send_chunk_to_player(player);
600 	memcpy((player->packet)+(player->packet_pos),packet,len);
601 	player->packet_pos+=len;
602 }
603 
604 
send_chunks(void)605 void send_chunks(void)
606 {
607 	struct player_list* p;
608 
609 	for (p=&players;p->next;p=p->next)
610  		send_chunk_to_player(&(p->next->member));
611 }
612 
613 
614 /* send a packet to all players except one */
615 /* if not_this_player is null, sends to all players */
sendall(unsigned char * packet,int len,struct player * not_this_player)616 void sendall(unsigned char *packet,int len, struct player * not_this_player)
617 {
618 	struct player_list* p;
619 
620 	if (!not_this_player)
621 		for (p=&players;p->next;p=p->next)
622  			send_packet(packet,len,(struct sockaddr*)(&(p->next->member.address)),0,p->next->member.id);
623 	else
624 		for (p=&players;p->next;p=p->next)
625 			if ((&(p->next->member))!=not_this_player)
626  				send_packet(packet,len,(struct sockaddr*)(&(p->next->member.address)),0,p->next->member.id);
627 }
628 
629 
630 /* send a packet to all players except one */
631 /* if not_this_player is null, sends to all players */
sendall_chunked(unsigned char * packet,int len,struct player * not_this_player)632 void sendall_chunked(unsigned char *packet,int len, struct player * not_this_player)
633 {
634 	struct player_list* p;
635 
636 	if (!not_this_player)
637 		for (p=&players;p->next;p=p->next)
638  			send_chunk_packet_to_player(packet,len,&(p->next->member));
639 	else
640 		for (p=&players;p->next;p=p->next)
641 			if ((&(p->next->member))!=not_this_player)
642  				send_chunk_packet_to_player(packet,len,&(p->next->member));
643 }
644 
645 
which_update(struct it * obj,my_double old_x,my_double old_y,my_double old_x_speed,my_double old_y_speed,unsigned int old_status,int old_ttl)646 int which_update(struct it *obj,my_double old_x,my_double old_y,my_double old_x_speed,my_double old_y_speed,unsigned int old_status,int old_ttl)
647 {
648 	int a=0;
649 
650 	if (old_ttl==obj->ttl)
651 	{
652 		if (old_x_speed==obj->xspeed&&old_y_speed==obj->yspeed)a=5;  /* update pos and status */
653 		if (old_x==obj->x&&old_y==obj->y)a=4; /* update speed and status */
654 	}
655 
656 	if (old_status==obj->status&&old_ttl==obj->ttl)
657 	{
658 		a=1;  /* update speed+coords */
659 
660 		if (old_x_speed==obj->xspeed&&old_y_speed==obj->yspeed)a=3; /* update pos */
661 		if (old_x==obj->x&&old_y==obj->y)
662 		{
663 			if(a==3)return -1;  /* nothing to update */
664 			a=2;  /* update speed */
665 		}
666 	}
667 	return a;
668 }
669 
670 /* send a packet to all players except one */
671 /* if not_this_player is null, sends to all players */
672 /* type is:
673 		0=full update
674 		1=update speed+coordinates
675 		2=update speed
676 		3=update coordinates
677 		4=update speed + status
678 		5=update coordinates + status
679 		6=update speed + status + ttl
680 		7=update coordinates + status + ttl
681 */
sendall_update_object(struct it * obj,struct player * not_this_player,int type)682 void sendall_update_object(struct it* obj, struct player * not_this_player,int type)
683 {
684 	struct player_list* p;
685 	int l;
686 	static unsigned char packet[32];
687 
688 	switch (type)
689 	{
690 		case 0: /* all */
691 		packet[0]=P_UPDATE_OBJECT;
692 		put_int(packet+1,obj->id);
693 		packet[5]=obj->update_counter;
694 		put_float(packet+6,obj->x);
695 		put_float(packet+10,obj->y);
696 		put_float(packet+14,obj->xspeed);
697 		put_float(packet+18,obj->yspeed);
698 		put_int16(packet+22,obj->status);
699 		put_int16(packet+24,obj->ttl);
700 		l=26;
701 		break;
702 
703 		case 1: /* coordinates and speed */
704 		packet[0]=P_UPDATE_OBJECT_POS;
705 		put_int(packet+1,obj->id);
706 		packet[5]=obj->update_counter;
707 		put_float(packet+6,obj->x);
708 		put_float(packet+10,obj->y);
709 		put_float(packet+14,obj->xspeed);
710 		put_float(packet+18,obj->yspeed);
711 		l=22;
712 		break;
713 
714 		case 2: /* speed */
715 		packet[0]=P_UPDATE_OBJECT_SPEED;
716 		put_int(packet+1,obj->id);
717 		packet[5]=obj->update_counter;
718 		put_float(packet+6,obj->xspeed);
719 		put_float(packet+10,obj->yspeed);
720 		l=14;
721 		break;
722 
723 		case 3: /* coordinates */
724 		packet[0]=P_UPDATE_OBJECT_COORDS;
725 		put_int(packet+1,obj->id);
726 		packet[5]=obj->update_counter;
727 		put_float(packet+6,obj->x);
728 		put_float(packet+10,obj->y);
729 		l=14;
730 		break;
731 
732 		case 4: /* speed and status */
733 		packet[0]=P_UPDATE_OBJECT_SPEED_STATUS;
734 		put_int(packet+1,obj->id);
735 		packet[5]=obj->update_counter;
736 		put_float(packet+6,obj->xspeed);
737 		put_float(packet+10,obj->yspeed);
738 		put_int16(packet+14,obj->status);
739 		l=16;
740 		break;
741 
742 		case 5: /* coordinates and status */
743 		packet[0]=P_UPDATE_OBJECT_COORDS_STATUS;
744 		put_int(packet+1,obj->id);
745 		packet[5]=obj->update_counter;
746 		put_float(packet+6,obj->x);
747 		put_float(packet+10,obj->y);
748 		put_int16(packet+14,obj->status);
749 		l=16;
750 		break;
751 
752 		case 6: /* speed and status and ttl */
753 		packet[0]=P_UPDATE_OBJECT_SPEED_STATUS_TTL;
754 		put_int(packet+1,obj->id);
755 		packet[5]=obj->update_counter;
756 		put_float(packet+6,obj->xspeed);
757 		put_float(packet+10,obj->yspeed);
758 		put_int16(packet+14,obj->status);
759 		put_int16(packet+16,obj->ttl);
760 		l=18;
761 		break;
762 
763 		case 7: /* coordinates and status and ttl */
764 		packet[0]=P_UPDATE_OBJECT_COORDS_STATUS_TTL;
765 		put_int(packet+1,obj->id);
766 		packet[5]=obj->update_counter;
767 		put_float(packet+6,obj->x);
768 		put_float(packet+10,obj->y);
769 		put_int16(packet+14,obj->status);
770 		put_int16(packet+16,obj->ttl);
771 		l=18;
772 		break;
773 
774 		default: /* don't update */
775 		return;
776 
777 	}
778 
779 	obj->update_counter++;
780 
781 	if (!not_this_player)
782 		for (p=&players;p->next;p=p->next)
783 			send_chunk_packet_to_player(packet,l,&(p->next->member));
784 	else
785 		for (p=&players;p->next;p=p->next)
786 			if ((&(p->next->member))!=not_this_player)
787  				send_chunk_packet_to_player(packet,l,&(p->next->member));
788 }
789 
790 
791 /* send update status packet to all players (except not_this_player if this is !NULL)*/
sendall_update_status(struct it * obj,struct player * not_this_player)792 void sendall_update_status(struct it* obj, struct player * not_this_player)
793 {
794 	struct player_list* p;
795 	static unsigned char packet[8];
796 
797 	packet[0]=P_UPDATE_STATUS;
798 	put_int(packet+1,obj->id);
799 	put_int16(packet+5,obj->status);
800 
801 	if (!not_this_player)
802 		for (p=&players;p->next;p=p->next)
803  			send_chunk_packet_to_player(packet,7,&(p->next->member));
804 	else
805 		for (p=&players;p->next;p=p->next)
806 			if ((&(p->next->member))!=not_this_player)
807  				send_chunk_packet_to_player(packet,7,&(p->next->member));
808 }
809 
810 
811 /* send hit packet to all players except not_this player (if !NULL)*/
sendall_hit(unsigned long id,unsigned char direction,unsigned char xoffs,unsigned char yoffs,struct player * not_this_player)812 void sendall_hit(unsigned long id,unsigned char direction,unsigned char xoffs,unsigned char yoffs,struct player* not_this_player)
813 {
814 	struct player_list* p;
815 	static unsigned char packet[8];
816 
817 	packet[0]=P_HIT;
818 	put_int(packet+1,id);
819 	packet[5]=direction;
820 	packet[6]=xoffs;
821 	packet[7]=yoffs;
822 
823 	if (!not_this_player)
824 		for (p=&players;p->next;p=p->next)
825  			send_chunk_packet_to_player(packet,8,&(p->next->member));
826 	else
827 		for (p=&players;p->next;p=p->next)
828 			if ((&(p->next->member))!=not_this_player)
829  				send_chunk_packet_to_player(packet,8,&(p->next->member));
830 }
831 
832 
833 /* sort players according to frags */
_qsort_cmp(const void * a,const void * b)834 int _qsort_cmp(const void *a,const void *b)
835 {
836 	int fa,fb,da,db;
837 	fa=(*((struct player**)a))->frags;
838 	fb=(*((struct player**)b))->frags;
839 	da=(*((struct player**)a))->deaths;
840 	db=(*((struct player**)b))->deaths;
841 
842 	if (fa>fb)return -1;
843 	if (fa==fb)
844 	{
845 		if (da<db)return -1;
846 		if (da>db)return 1;
847 		return 0;
848 	}
849 	return 1;
850 }
851 
852 
853 /* send info how many players are in the game and top score */
854 /* id=recipient's id */
855 /* if addr is NULL info is sent to all */
send_info(struct sockaddr * addr,int id)856 void send_info(struct sockaddr *addr,int id)
857 {
858 	unsigned char *packet;
859 	int p=active_players>TOP_PLAYERS_N?TOP_PLAYERS_N:active_players;
860 	int a,n,l;
861 	struct player **t;  /* table for qsort */
862 	struct player_list *q;
863 
864 	/* alloc memory */
865 	t=mem_alloc(active_players*sizeof(struct player*));
866 	if (!t)return;
867 	packet=mem_alloc(1+4+1+p*(MAX_NAME_LEN+4+4));
868 	if (!packet)return;
869 
870 	/* fill table for quicksort */
871 	for (a=0,q=(&players);q->next;a++,q=q->next)
872 		t[a]=&(q->next->member);
873 
874 	/* sort players */
875 	qsort(t,active_players,sizeof(struct player*),_qsort_cmp);
876 
877 	/* create packet header */
878 	packet[0]=P_INFO;
879 	put_int(packet+1,active_players);
880 	packet[5]=p;
881 	n=6;
882 
883 	/* put players into packet */
884 	for (a=0;a<p;a++)
885 	{
886 		put_int(packet+n,(t[a])->frags);
887 		put_int(packet+n+4,(t[a])->deaths);
888 		packet[n+8]=t[a]->color;
889 		l=strlen((t[a])->name)+1;
890 		memcpy(packet+n+9,(t[a])->name,l);
891 		n+=l+9;
892 	}
893 	if (!addr)sendall(packet,n,0);
894 	else send_packet(packet,n,addr,0,id);
895 
896 	mem_free(packet);
897 	mem_free(t);
898 }
899 
900 /* send message to a player */
901 /* name is name of player who sent the message (chat), NULL means it's from server */
send_message(struct player * player,unsigned char * name,unsigned char * msg)902 void send_message(struct player* player,unsigned char *name,unsigned char *msg)
903 {
904 	static unsigned char packet[256];
905 	int len;
906 
907 	packet[0]=P_MESSAGE;
908 	if (!name){snprintf(packet+1,256,"%s",msg);len=strlen(msg)+1+1;}
909 	else {snprintf(packet+1,256,"%s> %s",name,msg);len=strlen(name)+strlen(msg)+1+3;}
910 	if (len > 255)
911 		len = 255;
912 	send_chunk_packet_to_player(packet,len,player);
913 }
914 
915 
916 /* similar to send_message but sends to all except one or two players */
sendall_message(unsigned char * name,unsigned char * msg,struct player * not1,struct player * not2)917 void sendall_message(unsigned char *name,unsigned char *msg,struct player *not1,struct player* not2)
918 {
919 	static unsigned char packet[256];
920 	int len;
921 	struct player_list* p;
922 
923 	packet[0]=P_MESSAGE;
924 	if (!name){snprintf(packet+1,255,"%s",msg);len=strlen(msg)+1+1;}
925 	else {snprintf(packet+1,255,"%s> %s",name,msg);len=strlen(name)+strlen(msg)+1+3;}
926 	if (len > 255)
927 		len = 255;
928 	for (p=&players;p->next;p=p->next)
929 		if ((!not1||(&(p->next->member))!=not1)&&(!not2||(&(p->next->member))!=not2))
930  			send_chunk_packet_to_player(packet,len,&(p->next->member));
931 }
932 
933 
sendall_bell(void)934 void sendall_bell(void)
935 {
936 	static unsigned char packet;
937 	struct player_list* p;
938 
939 	packet=P_BELL;
940 	for (p=&players;p->next;p=p->next)
941  		send_chunk_packet_to_player(&packet,1,&(p->next->member));
942 
943 }
944 
945 
946 /* send new object information to given address */
send_new_obj(struct sockaddr * address,struct it * obj,int id)947 void send_new_obj(struct sockaddr* address, struct it* obj,int id)
948 {
949 	static unsigned char packet[32];
950 
951 	packet[0]=P_NEW_OBJ;
952 	put_int(packet+1,obj->id);
953 	put_int16(packet+5,obj->sprite);
954 	put_float(packet+7,obj->x);
955 	put_float(packet+11,obj->y);
956 	put_float(packet+15,obj->xspeed);
957 	put_float(packet+19,obj->yspeed);
958 	put_int16(packet+23,obj->status);
959 	packet[25]=obj->type;
960 	put_int16(packet+26,obj->ttl);
961 	send_packet(packet,28,address,0,id);
962 }
963 
964 
965 /* send new object information to given address */
send_new_obj_chunked(struct player * player,struct it * obj)966 void send_new_obj_chunked(struct player* player, struct it* obj)
967 {
968 	static unsigned char packet[32];
969 
970 	packet[0]=P_NEW_OBJ;
971 	put_int(packet+1,obj->id);
972 	put_int16(packet+5,obj->sprite);
973 	put_float(packet+7,obj->x);
974 	put_float(packet+11,obj->y);
975 	put_float(packet+15,obj->xspeed);
976 	put_float(packet+19,obj->yspeed);
977 	put_int16(packet+23,obj->status);
978 	packet[25]=obj->type;
979 	put_int16(packet+26,obj->ttl);
980 	send_chunk_packet_to_player(packet,28,player);
981 }
982 
983 
984 /* send player update to given player */
send_update_player(struct player * p)985 void send_update_player(struct player* p)
986 {
987 	static unsigned char packet[32];
988 	int a;
989 
990 	packet[0]=P_UPDATE_PLAYER;
991 	packet[1]=p->health;
992 	packet[2]=p->armor;
993 	for (a=0;a<ARMS;a++)
994 		put_int16(packet+3+(a<<1),p->ammo[a]);
995 	put_int(packet+3+2*ARMS,p->frags);
996 	put_int(packet+7+2*ARMS,p->deaths);
997 	packet[11+2*ARMS]=p->current_weapon;
998 	packet[12+2*ARMS]=p->weapons;
999 	send_chunk_packet_to_player(packet,13+2*ARMS,p);
1000 }
1001 
1002 /* send a packet to all players except one */
1003 /* if not_this_player is null, sends to all players */
sendall_new_object(struct it * obj,struct player * not_this_player)1004 void sendall_new_object(struct it* obj, struct player * not_this_player)
1005 {
1006 	struct player_list* p;
1007 
1008 	if (!not_this_player)
1009 		for (p=&players;p->next;p=p->next)
1010  			send_new_obj_chunked(&(p->next->member),obj);
1011 	else
1012 		for (p=&players;p->next;p=p->next)
1013 			if ((&(p->next->member))!=not_this_player)
1014  				send_new_obj_chunked(&(p->next->member),obj);
1015 }
1016 
1017 
1018 
1019 /* send all objects except one to specified player */
1020 /* if not_this_object is null, sends all objects */
send_objects(struct player * player,struct it * not_this_object)1021 void send_objects(struct player* player,struct it* not_this_object)
1022 {
1023 	struct object_list *p;
1024 
1025 	if (!not_this_object)
1026 		for(p=&objects;p->next;p=p->next)
1027 			send_new_obj_chunked(player,&(p->next->member));
1028 	else
1029 		for(p=&objects;p->next;p=p->next)
1030 			if((&p->next->member)!=not_this_object)
1031 				send_new_obj_chunked(player,&(p->next->member));
1032 }
1033 
1034 
1035 /* send all objects except one to specified player */
1036 /* if not_this_object is null, sends all objects */
send_change_level(struct player * player)1037 void send_change_level(struct player* player)
1038 {
1039 	unsigned char packet[64];
1040 
1041 	packet[0]=P_CHANGE_LEVEL;
1042 	put_int(packet+1,level_number);
1043 	memcpy(packet+5,level_checksum,33);
1044 	send_packet(packet,38,(struct sockaddr*)(&(player->address)),0,player->id);
1045 }
1046 
1047 
1048 /* send all objects in time queue to given player */
send_timeq_objects(struct player * player)1049 void send_timeq_objects(struct player *player)
1050 {
1051 	struct queue_list *p;
1052 
1053 	for (p=&time_queue;p->next;p=p->next)
1054 		send_new_obj_chunked(player,&(p->next->member));
1055 }
1056 
1057 
1058 /* remove player from server's list */
1059 /* delete player's hero and send message */
delete_player(struct player_list * q)1060 void delete_player(struct player_list *q)
1061 {
1062 	unsigned char packet[5];
1063 
1064 	/* delete object player's hero */
1065 	packet[0]=P_DELETE_OBJECT;
1066 	put_int(packet+1,q->member.obj->id);
1067 	sendall_chunked(packet,5,&(q->member));
1068 	delete_obj(q->member.obj->id);
1069 
1070 	mem_free (q->member.name);
1071 	q->prev->next=q->next;
1072 	if (!q->next)last_player=q->prev;   /* we're deleting last player of the list */
1073 	else q->next->prev=q->prev;
1074 	mem_free(q);
1075 	active_players--;
1076 	if (!active_players)last_player_left=get_time();
1077 }
1078 
1079 
1080 /* create a new object and fill with data and adds to hash table */
add_to_timeq(unsigned int id,unsigned char type,int ttl,int sprite,unsigned char pos,int status,my_double x,my_double y,my_double xspeed,my_double yspeed,void * data,unsigned long_long t)1081 struct it * add_to_timeq(
1082 	unsigned int id,
1083         unsigned char type,
1084         int ttl,
1085         int sprite,
1086         unsigned char pos,
1087         int status,
1088         my_double x,
1089         my_double y,
1090         my_double xspeed,
1091         my_double yspeed,
1092         void * data,unsigned long_long t)
1093 {
1094 	struct queue_list *p;
1095 	struct queue_list *q;
1096 
1097 	t+=get_time();
1098 	for (p=&time_queue;p->next&&p->next->member.last_updated<t;p=p->next);
1099 
1100 	q=p->next;
1101 
1102         p->next=mem_alloc(sizeof(struct queue_list));
1103         if (!p->next){p->next=q;return 0;}
1104         p=p->next;
1105         p->next=q;
1106         p->member.x=x;
1107         p->member.y=y;
1108         p->member.xspeed=xspeed;
1109         p->member.yspeed=yspeed;
1110         p->member.type=type;
1111         p->member.ttl=ttl;
1112 	p->member.id=id;
1113         p->member.sprite=sprite;
1114         p->member.anim_pos=pos;
1115         p->member.data=data;
1116         p->member.status=status|64;
1117 	p->member.last_updated=t;
1118         return &(p->member);
1119 }
1120 
1121 
1122 /* update time queue (respawning objects) */
1123 /* add objects timed out to the game */
update_timeq(void)1124 void update_timeq(void)
1125 {
1126 	unsigned long_long t=get_time();
1127 	struct queue_list *p,*q;
1128 	struct it *o;
1129 
1130 #define N p->next->member
1131 	for (p=&time_queue;p->next&&p->next->member.last_updated<=t;)
1132 	{
1133 		N.status&=~64;
1134 		o=new_obj(N.id,N.type,N.ttl,N.sprite,N.anim_pos,N.status,N.x,N.y,N.xspeed,N.yspeed,N.data);
1135 		sendall_update_status(o,0);
1136 		q=p->next->next;
1137 		mem_free(p->next);
1138 		p->next=q;
1139 	}
1140 #undef N
1141 }
1142 
1143 
1144 /* find player with given address */
1145 /* on unsuccess return 0 */
find_player(struct sockaddr_in * address,int id)1146 struct player_list* find_player(struct sockaddr_in *address,int id)
1147 {
1148 	struct player_list *p;
1149 
1150 	if (!address)
1151 	{
1152 		for(p=&players;p->next;p=p->next)
1153 		if (p->next->member.id==id)
1154 			return p->next;
1155 			return 0;
1156 	}
1157 	for(p=&players;p->next;p=p->next)
1158 		if (((p->next->member.address.sin_addr.s_addr)==(address->sin_addr.s_addr)&&(p->next->member.address.sin_port)==(address->sin_port))&&
1159 		     (p->next->member.id==id))
1160 			return p->next;
1161 	return 0;
1162 }
1163 
1164 
1165 
1166 /* create noise on given position */
create_noise(int x,int y,struct player * p)1167 void create_noise(int x,int y,struct player *p)
1168 {
1169 	struct it *o;
1170 
1171 	p->obj->status|=4096;
1172 	o=new_obj(id,T_NOISE,NOISE_TTL,noise_sprite,0,0,int2double(x),int2double(y),0,0,(void *)(p->id));
1173 	if (!o)return;
1174 	id++;
1175 	sendall_new_object(o,0);
1176 }
1177 
1178 
1179 
1180 /* read packet from socket */
read_data(void)1181 void read_data(void)
1182 {
1183 	unsigned char txt[256];
1184 	unsigned char txt1[256];
1185 	fd_set rfds;
1186 	struct timeval tv;
1187 	struct sockaddr_in client;
1188 	int a=sizeof(client);
1189 	static unsigned char packet[280];
1190 	struct player *p;
1191 	struct player_list *q;
1192 	unsigned char min,maj;
1193 	int s,x,y,l;
1194 
1195 	packet[279]=0;
1196 
1197 	tv.tv_sec=0;
1198 	tv.tv_usec=0;
1199 	FD_ZERO(&rfds);
1200 	FD_SET(fd,&rfds);
1201 	while (select(fd+1,&rfds,0,0,&tv))
1202 	{
1203 		if ((l=recv_packet(packet,256,(struct sockaddr*)(&client),&a,0,0,&s))==-1)
1204 			return;
1205 
1206  		last_packet_came=get_time();
1207 
1208 		switch(*packet)
1209 		{
1210 			case P_NEW_PLAYER:
1211 			if (l<6)break;   /* invalid packet */
1212 			{
1213 				unsigned long_long t;
1214 				if (packet[1]) /* this byte must be always 0 - version authentification, old versions transmitted color byte here */
1215 				{
1216 					message("Incompatible client version.\n",2);
1217 					packet[0]=P_PLAYER_REFUSED;
1218 					packet[1]=E_PLAYER_REFUSED;
1219 					send_packet(packet,2,(struct sockaddr*)(&client),0,last_player->member.id);
1220 					break;
1221 				}
1222 				maj=packet[2];
1223 				min=packet[3];
1224 				print_ip(txt1,client.sin_addr);
1225 				snprintf(txt,256,"Request for player #%d (client version %d.%d) from %s.\n",n_players,maj,min,txt1);
1226 				message(txt,2);
1227 				if (maj!=VERSION_MAJOR||min<MIN_CLIENT_VERSION_MINOR)
1228 				{
1229 					message("Incompatible client version. Player refused.\n",2);
1230 					packet[0]=P_PLAYER_REFUSED;
1231 					packet[1]=E_INCOMPATIBLE_VERSION;
1232 					send_packet(packet,2,(struct sockaddr*)(&client),0,last_player->member.id);
1233 					break;
1234 				}
1235 				if (strlen(packet+5) > MAX_NAME_LEN)
1236 				{
1237 					snprintf(txt,256,"Name too long, shortening it to %i characters\n",MAX_NAME_LEN);
1238 					message(txt,2);
1239 					packet[5+MAX_NAME_LEN]='\0';
1240 				}
1241 				find_birthplace(&x,&y);
1242 				if (add_player(packet[4],packet+5,&client,x,y)) /* failed to add player */
1243 				{
1244 					message("Player refused.\n",2);
1245 					packet[0]=P_PLAYER_REFUSED;
1246 					packet[1]=E_PLAYER_REFUSED;
1247 					send_packet(packet,2,(struct sockaddr*)(&client),0,last_player->member.id);
1248 					break;
1249 				}
1250 				snprintf(txt,256,"Player #%d accepted, name \"%s\", address %s.\n",n_players,packet+5,txt1);
1251 				message(txt,2);
1252 				snprintf(txt,256,"%s entered the game.",packet+5);
1253 				active_players++;
1254 				n_players++;
1255 				packet[0]=P_PLAYER_ACCEPTED;
1256 				last_player->member.obj->status|=1024;
1257 				put_int(packet+1,last_player->member.obj->id);
1258 				put_int16(packet+5,last_player->member.obj->sprite);
1259 				put_float(packet+7,last_player->member.obj->x);
1260 				put_float(packet+11,last_player->member.obj->y);
1261 				put_float(packet+15,last_player->member.obj->xspeed);
1262 				put_float(packet+19,last_player->member.obj->yspeed);
1263 				put_int16(packet+23,last_player->member.obj->status);
1264 				t=get_time();
1265 				put_long_long(packet+25,t-game_start);
1266 				put_int(packet+33,last_player->member.id);
1267 				packet[37]=VERSION_MAJOR;
1268 				packet[38]=VERSION_MINOR;
1269 				send_packet(packet,39,(struct sockaddr*)(&client),0,0);
1270 				send_change_level(&(last_player->member));
1271 				sendall_bell();
1272 				sendall_message(0,txt,0,0);
1273 				snprintf(txt,256,"There'%s %d %s in the game.",active_players==1?"s":"re",active_players,active_players==1?"player":"players");
1274 				sendall_message(0,txt,0,0);
1275 				send_info(0,0);
1276 			}
1277 			break;
1278 
1279 			case P_LEVEL_ACCEPTED:
1280 			q=find_player(&client,s);
1281 			if (!q)break;
1282 			if (q->member.current_level>=0)break;
1283 
1284 			q->member.current_level=level_number;
1285 			sendall_new_object(q->member.obj,&(q->member));
1286 			create_noise(double2int(q->member.obj->x),double2int(q->member.obj->y),&(q->member));
1287 			/* send all objects in the game */
1288 			send_objects(&(q->member),q->member.obj);
1289 			/* send all objects waiting for respawn */
1290 			send_timeq_objects(&(q->member));
1291 			break;
1292 
1293 			case P_INFO:
1294 			q=find_player(&client,s);
1295 			if (!q) send_info((struct sockaddr*)(&client),0);
1296 			else send_info((struct sockaddr*)(&client),q->member.id);
1297 			break;
1298 
1299 			case P_REENTER_GAME:
1300 			q=find_player(&client,s);
1301 			if (!q)break;
1302 			if (!(q->member.obj->status&1024)||(q->member.obj->status&4096))break;
1303 			find_birthplace(&x,&y);
1304 			create_noise(x,y,&(q->member));
1305 			q->member.obj->x=int2double(x);
1306 			q->member.obj->y=int2double(y);
1307 			sendall_update_object(q->member.obj,0,3);  /* update coordinates */
1308 			break;
1309 
1310 			case P_END:
1311 			if (nonquitable)break;
1312 			q=find_player(&client,s);
1313 			if (!q)break;
1314 			p=&(q->member);
1315 			packet[0]=P_END;
1316 			memcpy(packet+1,p->name,strlen(p->name)+1);
1317 			sendall(packet,2+strlen(p->name),0);
1318 			snprintf(txt,256,"Game terminated by player \"%s\".\n",p->name);
1319 			message(txt,2);
1320 			exit(0);
1321 
1322 			case P_QUIT_REQUEST:
1323 			q=find_player(&client,s);
1324 			if (!q)  /* this player has been deleted, but due to network inconsistency he doesn't know it */
1325 			{
1326 				packet[0]=P_PLAYER_DELETED;
1327 				send_packet(packet,1,(struct sockaddr*)(&client),0,last_player->member.id);
1328 				break;
1329 			}
1330 			snprintf(txt,256,"%s left the game.\n",q->member.name);
1331 			message(txt,2);
1332 			packet[0]=P_PLAYER_DELETED;
1333 			send_packet(packet,1,(struct sockaddr*)(&client),0,last_player->member.id);
1334 			snprintf(txt,256,"%s left the game.",q->member.name);
1335 			sendall_message(0,txt,0,0);
1336 			delete_player(q);
1337 			send_info(0,0);
1338 			break;
1339 
1340 			case P_KEYBOARD:
1341 			if (l<3)break;   /* invalid packet */
1342 			q=find_player(&client,s);
1343 			if (!q)break;
1344 			q->member.last_update=get_time();
1345 			q->member.keyboard_status.right=(packet[1])&1;
1346 			q->member.keyboard_status.left=((packet[1])>>1)&1;
1347 			q->member.keyboard_status.jump=((packet[1])>>2)&1;
1348 			q->member.keyboard_status.creep=((packet[1])>>3)&1;
1349 			q->member.keyboard_status.speed=((packet[1])>>4)&1;
1350 			q->member.keyboard_status.fire=((packet[1])>>5)&1;
1351 			q->member.keyboard_status.down_ladder=((packet[1])>>6)&1;
1352 			q->member.keyboard_status.weapon=packet[2];
1353 			break;
1354 
1355 			case P_MESSAGE:
1356 			if (l<2)break;   /* invalid packet */
1357 			q=find_player(&client,s);
1358 			if (!q)break;
1359 			sendall_message(q->member.name,packet+1,0,0);
1360 			snprintf(txt,256,"%s> %s\n",q->member.name,packet+1);
1361 			message(txt,1);
1362 			break;
1363 
1364 			default:
1365 			snprintf(txt,256,"Unknown packet: head=%d\n",*packet);
1366 			message(txt,2);
1367 			break;
1368 		}
1369 	}
1370 }
1371 
1372 
1373 /* compute collision of two objects */
1374 /* return value: 0=nothing */
1375 /*               1=collision */
collision(int x1,int y1,int t1,int s1,struct pos * p1,int x2,int y2,int t2,int s2,struct pos * p2)1376 int collision(int x1,int y1,int t1,int s1,struct pos* p1,int x2,int y2,int t2,int s2,struct pos *p2)
1377 {
1378 	int w1,w2,h1,h2;
1379 	unsigned char h=0,v=0;
1380 
1381 	get_dimensions(t1,s1,p1,&w1,&h1);
1382 	get_dimensions(t2,s2,p2,&w2,&h2);
1383 
1384 	if ((x2>=x1&&x2<=x1+w1-1)||(x2+w2-1>=x1&&x2+w2-1<=x1+w1-1))h=1;
1385 	if ((x1>=x2&&x1<=x2+w2-1)||(x1+w1-1>=x2&&x1+w1-1<=x2+w2-1))h=1;
1386 	if (!h)return 0;
1387 
1388 	if ((y2>=y1&&y2<=y1+h1-1)||(y2+h2-1>=y1&&y2+h2-1<=y1+h1-1))v=1;
1389 	if ((y1>=y2&&y1<=y2+h2-1)||(y1+h1-1>=y2&&y1+h1-1<=y2+h2-1))v=1;
1390 	if (!v)return 0;
1391 	return 1;
1392 }
1393 
1394 
1395 /* create corpse on given position and with color num */
1396 /* num is number of dead player */
create_corpse(int x,int y,int num)1397 void create_corpse(int x,int y,int num)
1398 {
1399 	struct it *o;
1400 	static unsigned char txt[32];
1401 	int a;
1402 	int xoffs=num>15?-15:-5;
1403 	int yoffs=num>15?-1:0;
1404 
1405 	sprintf(txt,"corpse%d",num);
1406 	if (find_sprite(txt,&a))return;
1407 
1408 	o=new_obj(id,T_CORPSE,CORPSE_TTL,a,0,0,int2double(x+xoffs),int2double(y+yoffs),0,0,0);
1409 	if (!o)return;
1410 	id++;
1411 	sendall_new_object(o,0);
1412 }
1413 
1414 
1415 /* create mess on given position */
1416 /* y1=y coordinate of the mess */
1417 /* y2=y coordinate of the player (place where blood gushes and guts fly from */
create_mess(int x,int y1,int y2)1418 void create_mess(int x,int y1,int y2)
1419 {
1420 	struct it *o;
1421 
1422 	o=new_obj(id,T_CORPSE,CORPSE_TTL,mess1_sprite,0,0,int2double(x),int2double(y1),0,0,0);
1423 	if (!o)return;
1424 	id++;
1425 	sendall_new_object(o,0);
1426 
1427 	o=new_obj(id,T_MESS,MESS_TTL,mess2_sprite,0,0,int2double(x),int2double(y2),-float2double(2*36),-float2double((double)1.4*36),0);
1428 	if (!o)return;
1429 	id++;
1430 	sendall_new_object(o,0);
1431 
1432 	o=new_obj(id,T_MESS,MESS_TTL,mess2_sprite,0,0,int2double(x),int2double(y2),float2double((double)2.8*36),-float2double(1*36),0);
1433 	if (!o)return;
1434 	id++;
1435 	sendall_new_object(o,0);
1436 
1437 	o=new_obj(id,T_MESS,MESS_TTL,mess2_sprite,0,0,int2double(x),int2double(y2),float2double(3*36),float2double((double).5*36),0);
1438 	if (!o)return;
1439 	id++;
1440 	sendall_new_object(o,0);
1441 
1442 	o=new_obj(id,T_MESS,MESS_TTL,mess3_sprite,0,0,int2double(x),int2double(y2),-float2double((double)2.5*36),float2double((double).3*36),0);
1443 	if (!o)return;
1444 	id++;
1445 	sendall_new_object(o,0);
1446 
1447 	o=new_obj(id,T_MESS,MESS_TTL,mess4_sprite,0,0,int2double(x),int2double(y2),-float2double((double)3.3*36),-float2double((double)2.1*36),0);
1448 	if (!o)return;
1449 	id++;
1450 	sendall_new_object(o,0);
1451 
1452 	o=new_obj(id,T_MESS,MESS_TTL,mess4_sprite,0,0,int2double(x),int2double(y2),float2double((double)2.9*36),-float2double((double)1.7*36),0);
1453 	if (!o)return;
1454 	id++;
1455 	sendall_new_object(o,0);
1456 
1457 	o=new_obj(id,T_MESS,MESS_TTL,mess4_sprite,0,0,int2double(x),int2double(y2),-float2double((double)1.3*36),float2double((double).8*36),0);
1458 	if (!o)return;
1459 	id++;
1460 	sendall_new_object(o,0);
1461 
1462 	o=new_obj(id,T_MESS,MESS_TTL,mess3_sprite,0,0,int2double(x),int2double(y2),float2double((double).7*36),-float2double((double)1.2*36),0);
1463 	if (!o)return;
1464 	id++;
1465 	sendall_new_object(o,0);
1466 }
1467 
1468 
1469 /* compute collision of given object with the others */
1470 /* return value: 1=delete this object */
1471 /*               0=don't delete */
1472 /* 		 2= delete this object but don't send delete packet */
dynamic_collision(struct it * obj)1473 int dynamic_collision(struct it *obj)
1474 {
1475 	struct it *p;
1476 	struct player_list *pl;
1477 	unsigned char txt[256];
1478 	struct it *o;
1479 	my_double b;
1480 	int a,c,s;
1481 	int px,py,h;
1482 
1483 #define OX (double2int(obj->x))
1484 #define OY (double2int(obj->y))
1485 #define PX (double2int(p->x))
1486 #define PY (double2int(p->y))
1487 #define A ((struct player*)(p->data))->armor
1488 #define H ((struct player*)(p->data))->health
1489 #define P ((struct player*)(p->data))
1490 #define MAX_AMMO(x) (weapon[x].max_ammo)
1491 
1492 
1493 	for (pl=&players;pl->next;pl=pl->next)
1494 	{
1495 		p=pl->next->member.obj;
1496 		if (p->type==T_PLAYER&&(p->status&1024))continue; /* dead player */
1497 		if (collision(OX,OY,obj->type,obj->status,sprites[obj->sprite].positions,PX,PY,p->type,p->status,sprites[p->sprite].positions))
1498 			switch(obj->type)
1499 			{
1500 				case T_AMMO_GRENADE:
1501 				{
1502 					unsigned char txt[256];
1503 					if (p->type!=T_PLAYER)break;
1504 					if (((struct player*)(p->data))->ammo[WEAPON_GRENADE]==MAX_AMMO(WEAPON_GRENADE))break;
1505 					((struct player*)(p->data))->ammo[WEAPON_GRENADE]+=weapon[WEAPON_GRENADE].add_ammo;
1506 					if (((struct player*)(p->data))->ammo[WEAPON_GRENADE]>MAX_AMMO(WEAPON_GRENADE))
1507 						((struct player*)(p->data))->ammo[WEAPON_GRENADE]=MAX_AMMO(WEAPON_GRENADE);
1508 /*					P->current_weapon=select_best_weapon(P);  */
1509 					send_update_player((struct player*)(p->data));
1510 					send_message((struct player*)(p->data),0,"You got grenades");
1511 					snprintf(txt,256,"%s got grenades.\n",((struct player*)(p->data))->name);
1512 					message(txt,1);
1513 					obj->status|=64;
1514 					add_to_timeq(obj->id,T_AMMO_GRENADE,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,AMMO_RESPAWN_TIME);
1515         				sendall_update_status(obj,0);
1516 				}
1517 				return 2;
1518 
1519 				case T_AMMO_GUN:
1520 				{
1521 					unsigned char txt[256];
1522 					if (p->type!=T_PLAYER)break;
1523 					if (((struct player*)(p->data))->ammo[0]==MAX_AMMO(0))break;
1524 
1525  					if(is_weapon_better((struct player*)(p->data), 0)
1526  						&& is_weapon_empty((struct player*)(p->data), 0))
1527  						P->current_weapon = 0;
1528 
1529 					((struct player*)(p->data))->ammo[0]+=weapon[0].add_ammo;
1530 					if (((struct player*)(p->data))->ammo[0]>MAX_AMMO(0))
1531 						((struct player*)(p->data))->ammo[0]=MAX_AMMO(0);
1532 /*					P->current_weapon=select_best_weapon(P);  */
1533 					send_update_player((struct player*)(p->data));
1534 					send_message((struct player*)(p->data),0,"You got a magazine");
1535 					snprintf(txt,256,"%s got a magazine.\n",((struct player*)(p->data))->name);
1536 					message(txt,1);
1537 					obj->status|=64;
1538 					add_to_timeq(obj->id,T_AMMO_GUN,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,AMMO_RESPAWN_TIME);
1539         				sendall_update_status(obj,0);
1540 				}
1541 				return 2;
1542 
1543 				case T_AMMO_SHOTGUN:
1544 				{
1545 					unsigned char txt[256];
1546 					if (p->type!=T_PLAYER)break;
1547 					if (((struct player*)(p->data))->ammo[1]==MAX_AMMO(1))break;
1548 
1549  					if(is_weapon_better((struct player*)(p->data), 1)
1550  						&& is_weapon_empty((struct player*)(p->data), 1))
1551  						P->current_weapon = 1;
1552 
1553 					((struct player*)(p->data))->ammo[1]+=weapon[1].add_ammo;
1554 					if (((struct player*)(p->data))->ammo[1]>MAX_AMMO(1))
1555 						((struct player*)(p->data))->ammo[1]=MAX_AMMO(1);
1556 /*					P->current_weapon=select_best_weapon(P);  */
1557 					send_update_player((struct player*)(p->data));
1558 					send_message((struct player*)(p->data),0,"You got shotgun shells");
1559 					snprintf(txt,256,"%s got shotgun shells.\n",((struct player*)(p->data))->name);
1560 					message(txt,1);
1561 					obj->status|=64;
1562 					add_to_timeq(obj->id,T_AMMO_SHOTGUN,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,AMMO_RESPAWN_TIME);
1563         				sendall_update_status(obj,0);
1564 				}
1565 				return 2;
1566 
1567 				case T_AMMO_RIFLE:
1568 				{
1569 					unsigned char txt[256];
1570 					if (p->type!=T_PLAYER)break;
1571 					if (((struct player*)(p->data))->ammo[3]==MAX_AMMO(3))break;
1572 
1573  					if(is_weapon_better((struct player*)(p->data), 3)
1574  						&& is_weapon_empty((struct player*)(p->data), 3))
1575  						P->current_weapon = 3;
1576 
1577 					((struct player*)(p->data))->ammo[3]+=weapon[3].add_ammo;
1578 					if (((struct player*)(p->data))->ammo[3]>MAX_AMMO(3))
1579 						((struct player*)(p->data))->ammo[3]=MAX_AMMO(3);
1580 /*					P->current_weapon=select_best_weapon(P);  */
1581 					send_update_player((struct player*)(p->data));
1582 					send_message((struct player*)(p->data),0,"You got cartridges");
1583 					snprintf(txt,256,"%s got cartridges.\n",((struct player*)(p->data))->name);
1584 					message(txt,1);
1585 					obj->status|=64;
1586 					add_to_timeq(obj->id,T_AMMO_RIFLE,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,AMMO_RESPAWN_TIME);
1587         				sendall_update_status(obj,0);
1588 				}
1589 				return 2;
1590 
1591 				case T_AMMO_UZI:
1592 				{
1593 					unsigned char txt[256];
1594 					if (p->type!=T_PLAYER)break;
1595 					if (((struct player*)(p->data))->ammo[2]==MAX_AMMO(2))break;
1596 
1597  					if(is_weapon_better((struct player*)(p->data), 2)
1598  						&& is_weapon_empty((struct player*)(p->data), 2))
1599  						P->current_weapon = 2;
1600 
1601 					((struct player*)(p->data))->ammo[2]+=weapon[2].add_ammo;
1602 					if (((struct player*)(p->data))->ammo[2]>MAX_AMMO(2))
1603 						((struct player*)(p->data))->ammo[2]=MAX_AMMO(2);
1604 /*					P->current_weapon=select_best_weapon(P); */
1605 					send_update_player((struct player*)(p->data));
1606 					send_message((struct player*)(p->data),0,"You got ammo for Uzi");
1607 					snprintf(txt,256,"%s got Uzi ammo.\n",((struct player*)(p->data))->name);
1608 					message(txt,1);
1609 					obj->status|=64;
1610 					add_to_timeq(obj->id,T_AMMO_UZI,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,AMMO_RESPAWN_TIME);
1611         				sendall_update_status(obj,0);
1612 				}
1613 				return 2;
1614 
1615 				case T_UZI:
1616 				{
1617 					unsigned char txt[256];
1618 					if (p->type!=T_PLAYER)break;
1619 					if ((((struct player*)(p->data))->ammo[2]==MAX_AMMO(2))&&((((struct player *)(p->data))->weapons)&4))break;
1620 
1621  					if(is_weapon_better((struct player*)(p->data), 2)
1622  						&& !is_weapon_usable((struct player*)(p->data), 2))
1623  						P->current_weapon = 2;
1624 
1625 					((struct player*)(p->data))->weapons|=4;
1626 					((struct player*)(p->data))->ammo[2]+=weapon[2].basic_ammo;
1627 					if (((struct player*)(p->data))->ammo[2]>MAX_AMMO(2))
1628 						((struct player*)(p->data))->ammo[2]=MAX_AMMO(2);
1629 //					P->current_weapon=select_best_weapon(P);
1630 					send_update_player((struct player*)(p->data));
1631 					send_message((struct player*)(p->data),0,"You got Uzi");
1632 					snprintf(txt,256,"%s got Uzi.\n",((struct player*)(p->data))->name);
1633 					message(txt,1);
1634 					obj->status|=64;
1635 					add_to_timeq(obj->id,T_UZI,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,WEAPON_RESPAWN_TIME);
1636         				sendall_update_status(obj,0);
1637 				}
1638 				return 2;
1639 
1640 				case T_RIFLE:
1641 				{
1642 					unsigned char txt[256];
1643 					if (p->type!=T_PLAYER)break;
1644 					if ((((struct player*)(p->data))->ammo[3]==MAX_AMMO(3))&&((((struct player *)(p->data))->weapons)&8))break;
1645 
1646  					if(is_weapon_better((struct player*)(p->data), 3)
1647  						&& !is_weapon_usable((struct player*)(p->data), 3))
1648  						P->current_weapon = 3;
1649 
1650 					((struct player*)(p->data))->weapons|=8;
1651 					((struct player*)(p->data))->ammo[3]+=weapon[3].basic_ammo;
1652 					if (((struct player*)(p->data))->ammo[3]>MAX_AMMO(3))
1653 						((struct player*)(p->data))->ammo[3]=MAX_AMMO(3);
1654 //					P->current_weapon=select_best_weapon(P);
1655 					send_update_player((struct player*)(p->data));
1656 					send_message((struct player*)(p->data),0,"You got sniper rifle");
1657 					snprintf(txt,256,"%s got sniper rifle.\n",((struct player*)(p->data))->name);
1658 					message(txt,1);
1659 					obj->status|=64;
1660 					add_to_timeq(obj->id,T_RIFLE,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,WEAPON_RESPAWN_TIME);
1661         				sendall_update_status(obj,0);
1662 				}
1663 				return 2;
1664 
1665 				case T_SHOTGUN:
1666 				{
1667 					unsigned char txt[256];
1668 					if (p->type!=T_PLAYER)break;
1669 					if ((((struct player*)(p->data))->ammo[1]==MAX_AMMO(1))&&((((struct player *)(p->data))->weapons)&2))break;
1670 
1671  					if(is_weapon_better((struct player*)(p->data), 1)
1672  						&& !is_weapon_usable((struct player*)(p->data), 1))
1673  						P->current_weapon = 1;
1674 
1675 					((struct player*)(p->data))->weapons|=2;
1676 					((struct player*)(p->data))->ammo[1]+=weapon[1].basic_ammo;
1677 					if (((struct player*)(p->data))->ammo[1]>MAX_AMMO(1))
1678 						((struct player*)(p->data))->ammo[1]=MAX_AMMO(1);
1679 //					P->current_weapon=select_best_weapon(P);
1680 					send_update_player((struct player*)(p->data));
1681 					send_message((struct player*)(p->data),0,"You got a shotgun");
1682 					snprintf(txt,256,"%s got a shotgun.\n",((struct player*)(p->data))->name);
1683 					message(txt,1);
1684 					obj->status|=64;
1685 					add_to_timeq(obj->id,T_SHOTGUN,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,WEAPON_RESPAWN_TIME);
1686         				sendall_update_status(obj,0);
1687 				}
1688 				return 2;
1689 
1690 				case T_INVISIBILITY:
1691 				{
1692 					unsigned char txt[256];
1693 					if (p->type!=T_PLAYER)break;
1694 
1695 					((struct player*)(p->data))->invisibility_counter=INVISIBILITY_DURATION;
1696 					p->status|=64;   /* hide player */
1697 					sendall_update_status(p,0);
1698 					send_message((struct player*)(p->data),0,"You got invisibility dope");
1699 					snprintf(txt,256,"%s got invisibility.\n",((struct player*)(p->data))->name);
1700 					message(txt,1);
1701 					obj->status|=64;
1702 					add_to_timeq(obj->id,T_INVISIBILITY,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,INVISIBILITY_RESPAWN_TIME);
1703         				sendall_update_status(obj,0);
1704 				}
1705 				return 2;
1706 
1707 				case T_ARMOR:
1708 				{
1709 					unsigned char txt[256];
1710 					if (p->type!=T_PLAYER)break;
1711 					if (((struct player*)(p->data))->armor>=100)break; /* he has 100% armor */
1712 					((struct player*)(p->data))->armor+=ARMOR_ADD;
1713 					if (((struct player*)(p->data))->armor>100)((struct player*)(p->data))->armor=100;
1714 					send_update_player((struct player*)(p->data));
1715 					send_message((struct player*)(p->data),0,"You got armor");
1716 					snprintf(txt,256,"%s got armor.\n",((struct player*)(p->data))->name);
1717 					message(txt,1);
1718 					obj->status|=64;
1719 					add_to_timeq(obj->id,T_ARMOR,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,ARMOR_RESPAWN_TIME);
1720         				sendall_update_status(obj,0);
1721 				}
1722 				return 2;
1723 
1724 				case T_MEDIKIT:
1725 				{
1726 					unsigned char txt[256];
1727 					if (p->type!=T_PLAYER)break;
1728 					if (((struct player*)(p->data))->health>=100)break; /* he's healthy */
1729 					((struct player*)(p->data))->health+=MEDIKIT_HEALTH_ADD;
1730 					if (((struct player*)(p->data))->health>100)((struct player*)(p->data))->health=100;
1731 					send_update_player((struct player*)(p->data));
1732 					send_message((struct player*)(p->data),0,"You picked up a medikit");
1733 					snprintf(txt,256,"%s picked up a medikit.\n",((struct player*)(p->data))->name);
1734 					message(txt,1);
1735 					obj->status|=64;
1736 					add_to_timeq(obj->id,T_MEDIKIT,0,obj->sprite,0,0,obj->x,obj->y,0,0,0,MEDIKIT_RESPAWN_TIME);
1737         				sendall_update_status(obj,0);
1738 				}
1739 				return 2;
1740 
1741 				case T_KILL:
1742 				if (p->type!=T_PLAYER)break;
1743 				a=(1-(double)A/100)*KILL_LETHALNESS;
1744 				c=KILL_ARMOR_DAMAGE;
1745 				if (a>=H)  /* player died */
1746 				{
1747 					((struct player*)(p->data))->deaths++;
1748 					send_message((struct player*)(p->data),0,"You killed yourself");
1749 					snprintf(txt,256,"%s suicides",((struct player*)(p->data))->name);
1750 					sendall_message(0,txt,(struct player*)(p->data),0);
1751 					snprintf(txt,256,"%s suicides.\n",((struct player*)(p->data))->name);
1752 					message(txt,2);
1753 
1754 					s=p->status;
1755 					px=PX;
1756 					py=PY;
1757 					h=H;
1758 					H=0;
1759 					p->xspeed=0;
1760 					p->yspeed=0;
1761 					p->status|=1024;  /* dead flag */
1762 					sendall_update_object(p,0,0); /* update everything */
1763 					send_update_player((struct player*)(p->data));   /* dead player */
1764 					send_info(0,0);
1765 					if (a-h>=OVERKILL)
1766 						create_mess(px,py+((s&256)?CREEP_HEIGHT:PLAYER_HEIGHT)-MESS_HEIGHT,py);
1767 					else
1768 						create_corpse(px,py+((s&256)?CREEP_HEIGHT:PLAYER_HEIGHT)-CORPSE_HEIGHT,((struct player*)(p->data))->color);
1769 				}
1770 				else
1771 				{
1772 					H-=a;  /* health */
1773 					A=(c>=A)?0:(A-c);   /* armor */
1774 					send_update_player((struct player*)(p->data));
1775 				}
1776 				return 0;
1777 
1778 				case T_SHRAPNEL:
1779 				if (p->type==T_CORPSE)
1780 				{
1781 					unsigned char packet[5];
1782 					px=PX;
1783 					py=PY;
1784 					packet[0]=P_DELETE_OBJECT;
1785 					put_int(packet+1,p->id);
1786 					sendall_chunked(packet,5,0);
1787 					delete_obj(p->id);
1788 					create_mess(px,py,py);
1789 					return 1;
1790 				}
1791 				case T_BULLET:
1792 				if (p->type!=T_PLAYER)break;
1793 				b=(obj->type==T_BULLET?FIRE_IMPACT:SHRAPNEL_IMPACT);
1794 				p->status|=128;
1795 				p->xspeed+=obj->xspeed>0?b:-b;
1796 				sendall_update_object(p,0,4);  /* update speed + status */
1797 				p->status&=~128;
1798 				a=(1-(double)A/100)*weapon[obj->status].lethalness*(2-double2int(obj->y-p->y)/(double)PLAYER_HEIGHT)*obj->ttl/weapon[obj->status].ttl;
1799 				c=weapon[obj->status].armor_damage*(2-double2int(obj->y-p->y)/(double)PLAYER_HEIGHT)*obj->ttl/weapon[obj->status].ttl;
1800 				if (a>=H)  /* player was slain */
1801 				{
1802 					o=&((find_in_table((int)(obj->data)))->member);  /* owner of the bullet */
1803 					((struct player*)(p->data))->deaths++;
1804 					if (o->data==p->data) /* suicide */
1805 					{
1806 						((struct player*)(o->data))->frags-=!!(((struct player*)(o->data))->frags);
1807 						send_message((struct player*)(o->data),0,"You killed yourself");
1808 						snprintf(txt,256,"%s suicides",((struct player*)(o->data))->name);
1809 						sendall_message(0,txt,(struct player*)(o->data),0);
1810 						snprintf(txt,256,"%s suicides.\n",((struct player*)(o->data))->name);
1811 						message(txt,2);
1812 					}
1813 					else
1814 					{
1815 						((struct player*)(o->data))->frags++;
1816 						snprintf(txt,256,"%s killed %s.",((struct player*)(o->data))->name,((struct player*)(p->data))->name);
1817 						sendall_message(0,txt,(struct player*)(o->data),(struct player*)(p->data));
1818 						snprintf(txt,256,"%s killed you",((struct player*)(o->data))->name);
1819 						send_message((struct player*)(p->data),0,txt);  /* the dead */
1820 						snprintf(txt,256,"You killed %s",((struct player*)(p->data))->name);
1821 						send_message((struct player*)(o->data),0,txt);  /* the dead */
1822 						snprintf(txt,256,"%s killed %s.\n",((struct player*)(o->data))->name,((struct player*)(p->data))->name);
1823 						message(txt,2);
1824 					}
1825 					s=p->status;
1826 					px=PX;
1827 					py=PY;
1828 					h=H;
1829 					H=0;
1830 					p->xspeed=0;
1831 					p->yspeed=0;
1832 					p->status|=1024;  /* dead flag */
1833 					sendall_update_object(p,0,0); /* update everything */
1834 					send_update_player((struct player*)(p->data));   /* dead player */
1835 					send_update_player((struct player*)(o->data));  /* owner of bullet/shrapnel */
1836 					send_info(0,0);
1837 					if (a-h>=OVERKILL)
1838 						create_mess(px,py+((s&256)?CREEP_HEIGHT:PLAYER_HEIGHT)-MESS_HEIGHT,py);
1839 					else
1840 						create_corpse(px,py+((s&256)?CREEP_HEIGHT:PLAYER_HEIGHT)-CORPSE_HEIGHT,((struct player*)(p->data))->color);
1841 				}
1842 				else
1843 				{
1844 					H-=a;  /* health */
1845 					A=(c>=A)?0:(A-c);   /* armor */
1846 					sendall_hit(p->id,obj->xspeed<0,OX-PX,OY-PY,0);
1847 					send_update_player((struct player*)(p->data));
1848 				}
1849 				return 1;
1850 			}
1851 	}
1852 	return 0;
1853 
1854 #undef MAX_AMMO
1855 #undef P
1856 #undef H
1857 #undef A
1858 #undef OX
1859 #undef OY
1860 #undef PX
1861 #undef PY
1862 }
1863 
1864 
1865 /* recompute objects positions */
update_game(void)1866 void update_game(void)
1867 {
1868 	static unsigned char packet[64];
1869         struct object_list *p;
1870 	struct player_list *q;
1871         int w,h,b,a;
1872 	unsigned char stop_x,stop_y;
1873 	my_double x,y,xs,ys;
1874 	my_double x1,y1;
1875 	unsigned char sy;
1876 	struct it *s;   /* for grenades throwing */
1877 	int status;
1878 	my_double DELTA_TIME;
1879 	unsigned long_long t;
1880 	unsigned int old_status;
1881 	int old_ttl;
1882 	my_double old_x,old_y,old_x_speed,old_y_speed;
1883 
1884         for(p=&objects;p->next;p=p->next)
1885         {
1886 		if (p->next->member.type==T_NOTHING)continue;
1887 		if (p->next->member.type==T_PLAYER&&(p->next->member.status&1024))continue;  /* dead player */
1888 		if (p->next->member.type==T_PLAYER&&(((struct player*)(p->next->member.data))->current_level)<0)  /* player hasn't entered the level yet */
1889 		{
1890 			send_change_level((struct player*)p->next->member.data);
1891 			continue;
1892 		}
1893 
1894 		old_status=p->next->member.status;
1895 		old_ttl=p->next->member.ttl;
1896 		old_x=p->next->member.x;
1897 		old_y=p->next->member.y;
1898 		old_x_speed=p->next->member.xspeed;
1899 		old_y_speed=p->next->member.yspeed;
1900 
1901 		x=p->next->member.x;
1902 		y=p->next->member.y;
1903 		xs=p->next->member.xspeed;
1904 		ys=p->next->member.yspeed;
1905 		status=p->next->member.status;
1906 
1907 		/* decrease invisibility counter of invisible player */
1908 		if ((p->next->member.type==T_PLAYER)&&(((struct player*)(p->next->member.data))->invisibility_counter))
1909 		{
1910 			((struct player*)(p->next->member.data))->invisibility_counter--;
1911 			if (!(((struct player*)(p->next->member.data))->invisibility_counter))
1912 			{
1913 				p->next->member.status&=~64;
1914 				sendall_update_status(&(p->next->member),0);
1915 			}
1916 		}
1917 
1918 
1919 		/* decrement time to live */
1920 		if (p->next->member.ttl>0)
1921 		{
1922 			p->next->member.ttl--;
1923 			/* create player */
1924 			if (p->next->member.type==T_NOISE&&p->next->member.ttl==(NOISE_TTL>>1))
1925 			{
1926 				/* find player */
1927 				q=find_player(0,(int)(p->next->member.data));
1928 				if (q) /* player is still in the game */
1929 				{
1930 					init_player(&(q->member),q->member.obj->x,q->member.obj->y);
1931 					q->member.obj->status&=~1024;
1932 					q->member.obj->status&=~4096;
1933 					sendall_update_object(q->member.obj,0,0);  /* update everything */
1934 					send_update_player(&(q->member));
1935 				}
1936 
1937 				goto cont_cycle;   /* that's all for T_NOISE at this moment */
1938 			}
1939 			/* grenades must be created after locking off */
1940 			/* not when shoot request comes */
1941 			if (p->next->member.type==T_PLAYER&&p->next->member.ttl==GRENADE_DELAY+HOLD_GUN_AFTER_SHOOT&&((struct player*)(p->next->member.data))->current_weapon==WEAPON_GRENADE)
1942 			{
1943 				s=new_obj(
1944 					id,
1945 					T_GRENADE,
1946 					weapon[WEAPON_GRENADE].ttl,
1947 					grenade_sprite,
1948 					0,
1949 					WEAPON_GRENADE,
1950 					add_int(p->next->member.x,p->next->member.status&2?2:PLAYER_WIDTH-2),
1951 					p->next->member.y+GRENADE_FIRE_YOFFSET,
1952 					p->next->member.xspeed+(p->next->member.status&2?-weapon[WEAPON_GRENADE].shell_xspeed:weapon[WEAPON_GRENADE].shell_xspeed),
1953 					p->next->member.yspeed+weapon[WEAPON_GRENADE].shell_yspeed,
1954 					(void *)(p->next->member.id));
1955 				id++;
1956 				sendall_new_object(s,0);
1957 			}
1958 			/* if ttl is 0, delete this object */
1959 			if (p->next->member.ttl<=0)
1960 			{
1961 				/* player's ttl means how long he holds the gun */
1962 				switch(p->next->member.type)
1963 				{
1964 					case T_PLAYER:
1965 					p->next->member.status&=~16;
1966 					break;
1967 
1968 					case T_GRENADE:
1969 					packet[0]=P_EXPLODE_GRENADE;
1970 					put_int(packet+1,id);
1971 					put_int(packet+5,p->next->member.id);
1972 					sendall_chunked(packet,9,0);
1973 
1974 					for (b=0;b<N_SHRAPNELS_EXPLODE;b++)
1975 					{
1976 						double angle=(double)b*2*M_PI/N_SHRAPNELS_EXPLODE;
1977 						my_double spd=add_int(mul_int(my_and(mul_int(weapon[WEAPON_GRENADE].speed,b+1),15),16),100);
1978 
1979 						new_obj(
1980 							id,
1981 							T_SHRAPNEL,
1982 							SHRAPNEL_TTL,
1983 							shrapnel_sprite[random()%N_SHRAPNELS],
1984 							0,
1985 							WEAPON_GRENADE,
1986 							p->next->member.x,
1987 							p->next->member.y,
1988 							p->next->member.xspeed+mul(spd,float2double(cos(angle))),
1989 							p->next->member.yspeed+mul(spd,float2double(sin(angle))),
1990 							p->next->member.data);
1991 						id++;
1992 					}
1993 					delete_obj(p->next->member.id);
1994 					if (!(p->next))return;
1995 					goto cont_cycle;
1996 
1997 					default:
1998 					packet[0]=P_DELETE_OBJECT;
1999 					put_int(packet+1,p->next->member.id);
2000 					sendall_chunked(packet,5,0);
2001 					delete_obj(p->next->member.id);
2002 					if (!(p->next))return;
2003 					goto cont_cycle;
2004 				}
2005 			}
2006 		}
2007 		/* maintain only objects that you are allowed to maintain */
2008 		if (!obj_attr[p->next->member.type].maintainer)goto dc;
2009 		if (!(obj_attr[p->next->member.type].maintainer&2))continue;
2010 
2011 
2012 		/* when not falling, slow down x motion */
2013 		if (!(p->next->member.status&8))p->next->member.xspeed=mul(p->next->member.xspeed,obj_attr[p->next->member.type].slow_down_x);
2014 
2015 		/* fall */
2016 		if (obj_attr[p->next->member.type].fall)
2017 		{
2018 			if (p->next->member.type!=T_SHRAPNEL)p->next->member.status|=8;
2019 			p->next->member.yspeed+=FALL_ACCEL;
2020 			/* but not too fast */
2021 			if (p->next->member.yspeed>MAX_Y_SPEED)p->next->member.yspeed=MAX_Y_SPEED;
2022 		}
2023 
2024 		t=get_time();
2025                 get_dimensions(p->next->member.type,p->next->member.status,sprites[p->next->member.sprite].positions,&w,&h);
2026 		DELTA_TIME=float2double(((double)((long_long)(t-p->next->member.last_updated)))/MICROSECONDS);
2027                 update_position(
2028                         &(p->next->member),
2029                         p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
2030                         p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
2031                         w,h,&stop_x,&stop_y);
2032 		p->next->member.last_updated=t;
2033 
2034 		/* walk up the stairs */
2035 		if (stop_x&&p->next->member.type==T_PLAYER&&!(p->next->member.status&256))
2036 		{
2037 			x1=p->next->member.x;
2038 			y1=p->next->member.y;
2039 			p->next->member.x=x;
2040 			p->next->member.y=y-int2double(1);
2041 	                update_position(
2042         	                &(p->next->member),
2043                 	        p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
2044                         	p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
2045 	                        w,h,0,&sy);
2046 			if ((p->next->member.xspeed>0&&p->next->member.x<=x1)||(p->next->member.xspeed<0&&p->next->member.x>=x1)) /* restore original values */
2047 			{
2048 				p->next->member.x=x1;
2049 				p->next->member.y=y1;
2050 			}
2051 			else
2052 			{
2053 				stop_y=sy;
2054 				stop_x=0;
2055 			}
2056 		}
2057 
2058 		if (stop_x)p->next->member.xspeed=-mul(p->next->member.xspeed,obj_attr[p->next->member.type].bounce_x);
2059 		if (my_abs(p->next->member.xspeed)<MIN_X_SPEED)
2060 		{
2061 			p->next->member.xspeed=0;
2062 			p->next->member.status&=~1;
2063 		}
2064 
2065 
2066 		if (stop_y)
2067 		{
2068 			p->next->member.yspeed=mul(p->next->member.yspeed,obj_attr[p->next->member.type].bounce_y);
2069 			p->next->member.yspeed=-p->next->member.yspeed;
2070 			if (my_abs(p->next->member.yspeed)<MIN_Y_SPEED)
2071 			{
2072 				p->next->member.yspeed=0;
2073 				if (stop_y==1)p->next->member.status&=~8;
2074 			}
2075 		}
2076 
2077 		if ((p->next->member.type==T_SHRAPNEL||p->next->member.type==T_BULLET)&&(stop_x||stop_y))  /* bullet and shrapnel die crashing into wall */
2078 		{
2079 			packet[0]=P_DELETE_OBJECT;
2080 			put_int(packet+1,p->next->member.id);
2081 			sendall_chunked(packet,5,0);
2082 			delete_obj(p->next->member.id);
2083 			if (!(p->next))break;
2084 			continue;
2085 		}
2086 dc:
2087 		/* compute collision with other objects */
2088 		a=dynamic_collision(&(p->next->member));
2089 		switch (a)
2090 		{
2091 			case 1:  /* object dies */
2092 			packet[0]=P_DELETE_OBJECT;
2093 			put_int(packet+1,p->next->member.id);
2094 			sendall_chunked(packet,5,0);
2095 
2096 			case 2:
2097 			delete_obj(p->next->member.id);
2098 			if (!(p->next))return;
2099 			goto cont_cycle;
2100 
2101 			case 0:   /* object still lives */
2102 				if (  /* send update but only when something's changed and client doesn't maintain the object */
2103 					(obj_attr[p->next->member.type].maintainer&4)&&  /* server sends update */
2104 					(x!=p->next->member.x||  /* something's changed */
2105 					y!=p->next->member.y||
2106 					xs!=p->next->member.xspeed||
2107 					ys!=p->next->member.yspeed||
2108 					status!=p->next->member.status))
2109 				{
2110 					a=which_update(&(p->next->member),old_x,old_y,old_x_speed,old_y_speed,old_status,old_ttl);
2111 					sendall_update_object(&(p->next->member),0,a);
2112 				}
2113 			break;
2114 		}
2115 cont_cycle:;
2116         }
2117 }
2118 
free_all_memory(void)2119 void free_all_memory(void)
2120 {
2121 	struct queue_list *t;
2122 	struct player_list *p;
2123 
2124 	/* delete players */
2125 	for (p=&players;p->next;)
2126 		delete_player(p->next);
2127 	/* delete objects */
2128 	while (last_obj!=(&objects))delete_obj(last_obj->member.id);
2129 
2130 	for (t=&time_queue;t->next;)
2131 	{
2132 		struct queue_list *q;
2133 
2134 		q=t->next->next;
2135 		mem_free(t->next);
2136 		t->next=q;
2137 	}
2138 
2139 	/* delete birthplaces */
2140 	if (n_birthplaces)mem_free(birthplace);
2141 
2142 	/* delete sprites */
2143 	free_sprites(0);
2144 
2145 	free_area();
2146 	if (level_checksum)mem_free(level_checksum);
2147 }
2148 
2149 /* fatal signal handler (sigsegv, sigabrt, ... ) */
signal_handler(int sig_num)2150 void signal_handler(int sig_num)
2151 {
2152 	unsigned char packet[16];
2153 	unsigned char txt[256];
2154 
2155 	packet[0]=P_END;
2156 	memcpy(packet+1,"server",7);
2157 
2158 	sendall(packet,8,0);
2159 	sendall(packet,8,0);
2160 	sendall(packet,8,0);
2161 	sendall(packet,8,0);
2162 	sendall(packet,8,0);
2163 	sendall(packet,8,0);
2164 	sendall(packet,8,0);
2165 	sendall(packet,8,0);
2166 	/* 800 % redundancy should be enough ;-) */
2167 
2168 	snprintf(txt,256,"Signal %d caught.\n",sig_num);
2169 	message(txt,2);
2170 	free_all_memory();
2171 	check_memory_leaks();
2172 #ifdef WIN32
2173 	hServerExitEvent=1;
2174 #else
2175 	signal(sig_num,SIG_DFL);
2176 	raise(sig_num);
2177 #endif
2178 }
2179 
2180 
2181 /* walk with given player */
walk_player(struct player * q,int direction,int speed,int creep)2182 void walk_player(struct player *q,int direction, int speed, int creep)
2183 {
2184 	int a;
2185 
2186 	unsigned int old_status=q->obj->status;
2187 	int old_ttl=q->obj->ttl;
2188 	my_double 	old_x=q->obj->x,
2189 			old_y=q->obj->y,
2190 			old_x_speed=q->obj->xspeed,
2191 			old_y_speed=q->obj->yspeed;
2192 
2193 
2194 	if ((q->obj->status&(512+16))==(512+16))return;  /* when throwing grenade can't walk */
2195 	if (creep)  /* creep */
2196 	{
2197 		a=MAX_SPEED_CREEP;
2198 		if (!(q->obj->status&256))q->obj->y+=CREEP_YOFFSET;
2199 		q->obj->status|=256;
2200 
2201 	}
2202 	else
2203 	{
2204 		a=speed?MAX_SPEED_WALK_FAST:MAX_X_SPEED;
2205 		if (q->obj->status&256)q->obj->y-=CREEP_YOFFSET;
2206 		q->obj->status&=~256;
2207 	}
2208 	switch (direction)
2209 	{
2210 		case 0:  /* stop */
2211 		q->obj->status&=~1;
2212 		q->obj->xspeed=0;
2213 		break;
2214 
2215 		case 1:  /* left */
2216 		q->obj->status|=1;
2217 		q->obj->xspeed-=WALK_ACCEL;
2218 		if (q->obj->xspeed<-a)q->obj->xspeed=-a;
2219 		break;
2220 
2221 		case 2:  /* right */
2222 		q->obj->status|=1;
2223 		q->obj->xspeed+=WALK_ACCEL;
2224 		if (q->obj->xspeed>a)q->obj->xspeed=a;
2225 		break;
2226 	}
2227 
2228 	a=which_update(q->obj,old_x,old_y,old_x_speed,old_y_speed,old_status,old_ttl);
2229 
2230 	sendall_update_object(q->obj,0,a);
2231 }
2232 
2233 
2234 /* jump with given player */
jump_player(struct player * p)2235 void jump_player(struct player *p)
2236 {
2237 	if (p->obj->status&8||p->obj->status&256)return;
2238 	p->obj->status|=8;
2239 	p->obj->yspeed=-SPEED_JUMP;
2240 	sendall_update_object(p->obj,0,4);   /* update speed + status */
2241 }
2242 
2243 
2244 /* change weapon of given player (w=new weapon) */
change_weapon_player(struct player * q,int w)2245 void change_weapon_player(struct player *q,int w)
2246 {
2247 	unsigned char txt[256];
2248 
2249 	if (!w)return;
2250 	w--;
2251 	if (q->current_weapon==w)return;
2252 	if (!(q->weapons&(1<<w)))
2253 		{send_message(q,0,"No weapon.");return;}
2254 	if (!(q->ammo[w]))
2255 		{send_message(q,0,"Not enough ammo.");return;}
2256 	q->current_weapon=w;
2257 	snprintf(txt,256,"%s takes %s.\n",q->name,weapon[w].name);
2258 	message(txt,1);
2259 	send_update_player(q);
2260 }
2261 
2262 
2263 /* shoot with given player */
2264 /* direction: 0=right, 1=left */
fire_player(struct player * q,int direction)2265 void fire_player(struct player *q,int direction)
2266 {
2267 	int a;
2268 	struct it *s;
2269 
2270 	if (!(q->obj->status&6)||(q->obj->status&256)||((q->obj->status&16)&&(q->obj->ttl>HOLD_GUN_AFTER_SHOOT)))return;
2271 	if (!q->ammo[q->current_weapon])
2272 	{
2273 		a=select_best_weapon(q);
2274 		if (a==q->current_weapon) return;
2275 		q->current_weapon=a;
2276 	}
2277 	q->ammo[q->current_weapon]--;
2278 	send_update_player(q);
2279 	q->obj->status&=~512;
2280 	if (q->current_weapon==WEAPON_SHOTGUN) /* shotgun */
2281 	{
2282 		s=new_obj(  /* SHELL */
2283 			id,
2284 			T_SHELL,
2285 			SHELL_TTL,
2286 			shotgun_shell_sprite,
2287 			0,
2288 			0,
2289 			add_int(q->obj->x,direction==1?0:PLAYER_WIDTH),
2290 			q->obj->y+FIRE_YOFFSET,
2291 			q->obj->xspeed+(direction==1?-weapon[1].shell_xspeed:weapon[1].shell_xspeed),
2292 			weapon[1].shell_yspeed,
2293 			(void *)(q->obj->id));
2294 		id++;
2295 		sendall_new_object(s,0);
2296 		s=new_obj(  /* straight */
2297 			id,
2298 			T_BULLET,
2299 			weapon[q->current_weapon].ttl,
2300 			slug_sprite,
2301 			0,
2302 			q->current_weapon,
2303 			add_int(q->obj->x,direction==1?-2:PLAYER_WIDTH+2),
2304 			q->obj->y+FIRE_YOFFSET,
2305 			q->obj->xspeed+(direction==1?-weapon[q->current_weapon].speed:weapon[q->current_weapon].speed),
2306 			0,
2307 			(void *)(q->obj->id));
2308 		id++;
2309 		sendall_new_object(s,0);
2310 		s=new_obj(  /* straight */
2311 			id,
2312 			T_BULLET,
2313 			weapon[q->current_weapon].ttl,
2314 			slug_sprite,
2315 			0,
2316 			q->current_weapon,
2317 			add_int(q->obj->x,direction==1?0:PLAYER_WIDTH),
2318 			q->obj->y+FIRE_YOFFSET+int2double(1),
2319 			q->obj->xspeed+(direction==1?-weapon[q->current_weapon].speed:weapon[q->current_weapon].speed),
2320 			0,
2321 			(void *)(q->obj->id));
2322 		id++;
2323 		sendall_new_object(s,0);
2324 		s=new_obj(  /* one up */
2325 			id,
2326 			T_BULLET,
2327 			weapon[q->current_weapon].ttl,
2328 			slug_sprite,
2329 			0,
2330 			q->current_weapon,
2331 			add_int(q->obj->x,direction==1?-1:PLAYER_WIDTH+1),
2332 			q->obj->y+FIRE_YOFFSET,
2333 			q->obj->xspeed+(direction==1?-weapon[q->current_weapon].speed:weapon[q->current_weapon].speed),
2334 			float2double((double).1*36),
2335 			(void *)(q->obj->id));
2336 		id++;
2337 		sendall_new_object(s,0);
2338 		s=new_obj(  /* two up */
2339 			id,
2340 			T_BULLET,
2341 			weapon[q->current_weapon].ttl,
2342 			slug_sprite,
2343 			0,
2344 			q->current_weapon,
2345 			add_int(q->obj->x,direction==1?0:PLAYER_WIDTH),
2346 			q->obj->y+FIRE_YOFFSET-int2double(1),
2347 			q->obj->xspeed+(direction==1?-weapon[q->current_weapon].speed:weapon[q->current_weapon].speed),
2348 			float2double((double).15*36),
2349 			(void *)(q->obj->id));
2350 		id++;
2351 		sendall_new_object(s,0);
2352 		s=new_obj(  /* one down */
2353 			id,
2354 			T_BULLET,
2355 			weapon[q->current_weapon].ttl,
2356 			slug_sprite,
2357 			0,
2358 			q->current_weapon,
2359 			add_int(q->obj->x,direction==1?0:PLAYER_WIDTH),
2360 			q->obj->y+FIRE_YOFFSET+int2double(1),
2361 			q->obj->xspeed+(direction==1?-weapon[q->current_weapon].speed:weapon[q->current_weapon].speed),
2362 			-float2double((double).1*36),
2363 			(void *)(q->obj->id));
2364 		id++;
2365 		sendall_new_object(s,0);
2366 		s=new_obj(  /* two down */
2367 			id,
2368 			T_BULLET,
2369 			weapon[q->current_weapon].ttl,
2370 			slug_sprite,
2371 			0,
2372 			q->current_weapon,
2373 			add_int(q->obj->x,direction==1?-1:PLAYER_WIDTH+1),
2374 			q->obj->y+FIRE_YOFFSET,
2375 			q->obj->xspeed+(direction==1?-weapon[q->current_weapon].speed:weapon[q->current_weapon].speed),
2376 			-float2double((double).15*36),
2377 			(void *)(q->obj->id));
2378 		id++;
2379 		sendall_new_object(s,0);
2380 	}
2381 	else
2382 	{
2383 		if (q->current_weapon!=WEAPON_GRENADE)  /* not grenades */
2384 		{
2385 			s=new_obj(  /* SHELL */
2386 				id,
2387 				T_SHELL,
2388 				SHELL_TTL,
2389 				shell_sprite,
2390 				0,
2391 				0,
2392 				add_int(q->obj->x,direction==1?0:PLAYER_WIDTH),
2393 				q->obj->y+FIRE_YOFFSET,
2394 				q->obj->xspeed+(direction==1?-weapon[q->current_weapon].shell_xspeed:weapon[q->current_weapon].shell_xspeed),
2395 				weapon[q->current_weapon].shell_yspeed,
2396 				(void *)(q->obj->id));
2397 			id++;
2398 			sendall_new_object(s,0);
2399 			s=new_obj(
2400 				id,
2401 				T_BULLET,
2402 				weapon[q->current_weapon].ttl,
2403 				bullet_sprite,
2404 				0,
2405 				q->current_weapon,
2406 				add_int(q->obj->x,direction==1?0:PLAYER_WIDTH),
2407 				q->obj->y+FIRE_YOFFSET,
2408 				q->obj->xspeed+(direction==1?-weapon[q->current_weapon].speed:weapon[q->current_weapon].speed),
2409 				0,
2410 				(void *)(q->obj->id));
2411 			id++;
2412 			sendall_new_object(s,0);
2413 		}
2414 		else  /* grenades */
2415 		{
2416 			q->obj->status|=512;
2417 			q->obj->status&=~1;
2418 		}
2419 	}
2420 	q->obj->xspeed+=(direction==1)?weapon[q->current_weapon].impact:-weapon[q->current_weapon].impact;
2421 	q->obj->status|=16;
2422 	q->obj->status|=32;
2423 	q->obj->ttl=weapon[q->current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
2424 	sendall_update_object(q->obj,0,6);  /* update speed and status and ttl */
2425 	q->obj->status&=~32;
2426 }
2427 
2428 
2429 /* update given player (jump, shoot, creep, change weapon) */
move_player(struct player * p)2430 void move_player(struct player *p)
2431 {
2432 	int a;
2433 
2434 	if (p->obj->status&1024)return;   /* dead player */
2435 
2436 	if (p->keyboard_status.down_ladder)  /* climb down a ladder */
2437 		p->obj->status|=2048;
2438 	else
2439 		p->obj->status&=~2048;
2440 
2441 	if (p->keyboard_status.jump)
2442 		jump_player(p);
2443 	if (p->keyboard_status.right)
2444 	{
2445 		if ((p->obj->status&6)==4)   /* walk right */
2446 			walk_player(p,2,p->keyboard_status.speed,p->keyboard_status.creep);
2447 		else
2448 		{
2449                         if ((p->obj->status)&1)
2450                                 walk_player(p,0,p->keyboard_status.speed,p->keyboard_status.creep);   /* stop */
2451                         else
2452                         {
2453                                 a=(p->obj->status&6)>>1;
2454                                 p->obj->status&=~6;
2455                                 p->obj->status|=(a==1)?0:4;
2456                                 sendall_update_status(p->obj,0);
2457 			}
2458 		}
2459 	}
2460 
2461 	if (p->keyboard_status.left)
2462 	{
2463 		if ((p->obj->status&6)==2)   /* walk right */
2464 			walk_player(p,1,p->keyboard_status.speed,p->keyboard_status.creep);
2465 		else
2466 		{
2467                         if ((p->obj->status)&1)
2468                                 walk_player(p,0,p->keyboard_status.speed,p->keyboard_status.creep);   /* stop */
2469                         else
2470                         {
2471                                 a=(p->obj->status&6)>>1;
2472                                 p->obj->status&=~6;
2473                                 p->obj->status|=(a==2)?0:2;
2474                                 sendall_update_status(p->obj,0);
2475 			}
2476 		}
2477 	}
2478 	change_weapon_player(p,p->keyboard_status.weapon);
2479 	if (p->keyboard_status.fire)
2480 		fire_player(p,(p->obj->status&6)>>1);
2481 }
2482 
2483 
2484 /* update players, kick out not responding players */
update_players(void)2485 void update_players(void)
2486 {
2487 	struct player_list *p;
2488 	unsigned char txt[256];
2489 	unsigned char packet;
2490 	unsigned long_long t=get_time();
2491 
2492 	for (p=&players;p->next;p=p->next)
2493 	{
2494 		/* this player is dead - delete him */
2495 		if (t-(p->next->member).last_update>=MAX_DUMB_TIME)
2496 		{
2497 			snprintf(txt,256,"%s not responding. Kicked out of the game.\n",p->next->member.name);
2498 			message(txt,2);
2499 			packet=P_PLAYER_DELETED;
2500 			send_packet(&packet,1,(struct sockaddr*)(&(p->next->member.address)),0,last_player->member.id);
2501 			snprintf(txt,256,"%s was kicked out of the game.",p->next->member.name);
2502 			sendall_message(0,txt,0,0);
2503 			delete_player(p->next);
2504 			if (!(p->next))break;
2505 		}
2506 		else
2507 			move_player(&(p->next->member));
2508 	}
2509 }
2510 
2511 
2512 /* write help message to stdout */
print_help(void)2513 void print_help(void)
2514 {
2515 #ifdef WIN32
2516 	printf(	"0verkill server.\n"
2517 		"(c)2000 Brainsoft\n"
2518 		"Portions (c) 2000 by Filip Konvicka\n"
2519 		"Usage: server [-nh] [-l <level_number>] [-p <port number>] [-i username[/password]] [-I] [-r]\n"
2520 		"-i		Installs as a service\n"
2521 		"-I		Installs with the LOCAL_SYSTEM account.\n"
2522 		"-r		Stops and removes the service\n"
2523 		"-n		Server can't be ended by client\n"
2524 		"You must be an administrator in order to install/remove a service.\n");
2525 #else
2526 	printf(	"0verkill server.\n"
2527 		"(c)2000 Brainsoft\n"
2528 #ifdef __EMX__
2529 		"Portions (c) 2000 by Mikulas Patocka\n"
2530 #endif
2531 		"Usage: server [-nh] [-l <level number>] [-p <port number>]\n"
2532 		"-n		Server can't be ended by client\n"
2533 		);
2534 #endif
2535 }
2536 
2537 
parse_command_line(int argc,char ** argv)2538 void parse_command_line(int argc,char **argv)
2539 {
2540 	int a;
2541 	char *c;
2542 
2543 	while(1)
2544 	{
2545 #ifdef WIN32
2546 		a=getopt(argc,argv,"hl:np:ri:Ic");
2547 #else
2548 		a=getopt(argc,argv,"hl:np:");
2549 #endif
2550 		switch(a)
2551 		{
2552 			case EOF:
2553 			return;
2554 
2555 			case '?':
2556 			case ':':
2557 			EXIT(1);
2558 
2559 #ifdef WIN32
2560 			case 'c':
2561 				break;	/* run as console app */
2562 			case 'r':	/* remove service */
2563 				CmdRemoveService();
2564 				EXIT(1);
2565 			case 'i': {	/* install service */
2566 				char	username[80],
2567 						password[80],
2568 						*user=NULL,
2569 						*pass=NULL;
2570 				if ( optarg ) {
2571 					username[sizeof(username)-1]=0;
2572 					user=username;
2573 					if ( (pass=strchr(optarg, '/'))==NULL ) {
2574 						strcpy(username, optarg);
2575 						memcpy(username, optarg, sizeof(username)-1);
2576 						password[0]=0;
2577 					}
2578 					else {
2579 						int		size=pass-optarg;
2580 						if ( size>sizeof(username)-1 )
2581 							size=sizeof(username)-1;
2582 						memcpy(username, optarg, size);
2583 						username[size]=0;
2584 						pass++;
2585 						size=strlen(pass);
2586 						if ( size>sizeof(password)-1 )
2587 							size=sizeof(password)-1;
2588 						memcpy(password, pass, size);
2589 					}
2590 				}
2591 				CmdInstallService(user, pass, NULL);
2592 				EXIT(1);
2593 			}
2594 			case 'I': {	/* install service */
2595 				CmdInstallService(NULL, NULL, NULL);
2596 				EXIT(1);
2597 			}
2598 #endif
2599 
2600 			case 'h':
2601 			print_help();
2602 			EXIT(0);
2603 
2604 			case 'p':
2605 			port=strtoul(optarg,&c,10);
2606 			if (*c){ERROR("Error: Not a number.\n");EXIT(1);}
2607 			if (errno==ERANGE)
2608 			{
2609 				if (!port){ERROR("Error: Number underflow.\n");EXIT(1);}
2610 				else {ERROR("Error: Number overflow.\n");EXIT(1);}
2611 			}
2612 			break;
2613 
2614 			case 'l':
2615 			level_number=strtoul(optarg,&c,10);
2616 			if (*c){ERROR("Error: Not a number.\n");EXIT(1);}
2617 			if (errno==ERANGE)
2618 			{
2619 				if (!level_number){ERROR("Error: Number underflow.\n");EXIT(1);}
2620 				else {ERROR("Error: Number overflow.\n");EXIT(1);}
2621 			}
2622 			break;
2623 
2624 			case 'n':
2625 			nonquitable=1;
2626 			break;
2627 		}
2628 	}
2629 }
2630 
2631 
2632 /*-----------------------------------------------------------------------------------*/
server(void)2633 int server(void)
2634 {
2635 	int a;
2636 	unsigned char txt[256];
2637 	unsigned long_long last_time;
2638 	unsigned char *LEVEL;
2639 
2640 	last_player=&players;
2641 	last_obj=&objects;
2642 
2643 	snprintf(txt,256,"Running 0verkill server version %d.%d\n",VERSION_MAJOR,VERSION_MINOR);
2644 	message(txt,2);
2645 #ifdef WIN32
2646 	snprintf(txt,256,"This is 0verkill server for Win32, build #%u\n",VERSION_PORT);
2647 	message(txt,2);
2648 #endif
2649 	message("Initialization.\n",2);
2650 #ifdef WIN32
2651 	message("Starting Windows Sockets\n",2);
2652 	{
2653 		WSADATA	wd;
2654 		WSAStartup(0x101, &wd);
2655 		snprintf(txt,256,"Started WinSock version %X.%02X\n", wd.wVersion/0x100, wd.wVersion&0xFF);
2656 		message(txt, 2);
2657 	}
2658 #endif
2659 	init_area();  /* initialize playing area */
2660 	hash_table_init();
2661 
2662 #ifdef WIN32
2663 	if ( !consoleApp )
2664 		ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 2000);
2665 #endif
2666 
2667 	message("Loading sprites.\n",2);
2668 	load_sprites(DATA_PATH GAME_SPRITES_FILE); /* players, corpses, bullets, ... */
2669 	if (find_sprite("bullet",&bullet_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"bullet\".\n");ERROR(msg);EXIT(1);}
2670 	if (find_sprite("slug",&slug_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"slug\".\n");ERROR(msg);EXIT(1);}
2671 	if (find_sprite("shell",&shell_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"shell\".\n");ERROR(msg);EXIT(1);}
2672 	if (find_sprite("sshell",&shotgun_shell_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"sshell\".\n");ERROR(msg);EXIT(1);}
2673 	if (find_sprite("grenade",&grenade_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"grenade\".\n");ERROR(msg);EXIT(1);}
2674 	if (find_sprite("mess1",&mess1_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"mess1\".\n");ERROR(msg);EXIT(1);}
2675 	if (find_sprite("mess2",&mess2_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"mess2\".\n");ERROR(msg);EXIT(1);}
2676 	if (find_sprite("mess3",&mess3_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"mess3\".\n");ERROR(msg);EXIT(1);}
2677 	if (find_sprite("mess4",&mess4_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"mess4\".\n");ERROR(msg);EXIT(1);}
2678 	if (find_sprite("noise",&noise_sprite)){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"noise\".\n");ERROR(msg);EXIT(1);}
2679 	for (a=0;a<N_SHRAPNELS;a++)
2680 	{
2681 		sprintf(txt,"shrapnel%d",a+1);
2682 		if (find_sprite(txt,&shrapnel_sprite[a])){unsigned char msg[256];snprintf(msg,256,"Can't find sprite \"%s\".\n",txt);ERROR(msg);EXIT(1);}
2683 	}
2684 
2685 	LEVEL=load_level(level_number);
2686 	level_checksum=md5_level(level_number);
2687 	if (!LEVEL){char txt[256];snprintf(txt,256,"Can't load level number %d\n",level_number);ERROR(txt);EXIT(1);}
2688 	snprintf(txt,256,"Loading level \"%s\"....\n",LEVEL);
2689 	message(txt,2);
2690 	snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,LEVEL_SPRITES_SUFFIX);
2691 	message("Loading level graphics.\n",2);
2692 	load_sprites(txt);
2693 	snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,STATIC_DATA_SUFFIX);
2694 	message("Loading level map.\n",2);
2695 	load_data(txt);
2696 	snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,DYNAMIC_DATA_SUFFIX);
2697 	message("Loading level objects.\n",2);
2698 	mem_free(LEVEL);
2699 	load_dynamic(txt);
2700 
2701 	message("Initializing socket.\n",2);
2702 	init_socket();  /* initialize socket */
2703 
2704 	message("Installing signal handlers.\n",2);
2705 	signal(SIGINT,signal_handler);
2706 	signal(SIGTERM,signal_handler);
2707 	signal(SIGFPE,signal_handler);
2708 	signal(SIGILL,signal_handler);
2709 	signal(SIGABRT,signal_handler);
2710 #ifndef WIN32
2711 	signal(SIGBUS,signal_handler);
2712 	signal(SIGQUIT,signal_handler);
2713 #endif
2714 	message("Game started.\n",2);
2715 
2716 #ifdef __EMX__
2717 	DosSetPriority(PRTYS_PROCESS, PRTYC_FOREGROUNDSERVER, 1, 0);
2718 #endif
2719 
2720 	game_start=get_time();
2721 	srandom(game_start);
2722 
2723 #ifdef WIN32
2724 	if ( !consoleApp )
2725 		ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0);
2726 #endif
2727 
2728 	last_time=get_time();
2729 again:
2730 	last_time+=PERIOD_USEC;
2731 	if (get_time()-last_time>PERIOD_USEC*100)last_time=get_time();
2732 	read_data();
2733 	update_timeq();
2734 	update_game();
2735 	update_players();    /* MUST come after update_game otherwise when player shoots he hit himself */
2736 	send_chunks();
2737 	last_tick=get_time();
2738 	if (!active_players&&(last_tick-last_player_left)>DELAY_BEFORE_SLEEP_USEC&&(last_tick-last_packet_came)>DELAY_BEFORE_SLEEP_USEC)
2739 	{
2740 #ifndef WIN32
2741 		message("Sleep\n",2);
2742 		{
2743 			fd_set fds;
2744 			FD_ZERO(&fds);
2745 			FD_SET(fd,&fds);
2746 			select(fd+1,&fds,0,0,0);
2747 		}
2748 		message("Wakeup\n",2);
2749 #else
2750 		WaitForSingleObject(fd, 500); /* wait max. 0.5 seconds, then we must test hServerExitEvent */
2751 #endif
2752 	}
2753 #ifdef WIN32
2754 	/* we must return so that the service can be properly stopped */
2755 	if ( hServerExitEvent )
2756 		return 0;
2757 #endif
2758 	sleep_until(last_time+PERIOD_USEC);
2759  	goto again;
2760 
2761 	return 0;
2762 }
2763 
2764 
main(int argc,char ** argv)2765 int main(int argc, char **argv)
2766 {
2767 	int a;
2768 
2769 #ifdef WIN32
2770 	SERVICE_TABLE_ENTRY	dispatchTable[]={{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain}, {NULL, NULL}};
2771 	if ( argc==1 ) {
2772 		if ( !StartServiceCtrlDispatcher(dispatchTable) ) {
2773 			globErr=GetLastError();
2774 			/*LPTSTR	pszError=CErrorContext::LoadWin32ErrorString(globErr);
2775 			::CharToOem(pszError, pszError);
2776 			_tprintf(_T("StartServiceCtrlDispatcher failed: %u"), globErr);
2777 			if ( pszError!=NULL ) {
2778 				_tprintf(_T(": %s\r\n"), pszError);
2779 				::LocalFree(pszError);
2780 			}
2781 			else
2782 				_tprintf(_T("\r\n"));*/
2783 			AddToMessageLog("StartServiceCtrlDispatcher failed", 0);
2784 		}
2785 	}
2786 	consoleApp=1;
2787 #endif
2788 	parse_command_line(argc,argv);
2789 
2790 	a=server();
2791 	free_all_memory();
2792 	check_memory_leaks();
2793 	return a;
2794 }
2795