1 /* zeRace dedicated server */
8 /* each client has his data */
11 char pseudo[MAXLINELENGTH];
16 } clients [MAX_CLIENTS];
22 struct _tracklist *tracklist;
26 /* return the id of a connected address */
27 int lookup(IPaddress address)
30 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected && clients[i].address.host==address.host && clients[i].address.port==address.port) return i;
35 /* announce the server on internet */
36 void announce(char *name,int clients)
42 "POST /zerace/announce.php HTTP/1.0\n"
43 "Host: royale.zerezo.com\n"
44 "User-Agent: zeRace dedicated server " VERSION "\n"
45 "Content-Type: application/x-www-form-urlencoded\n"
46 "Content-Length: 99999\n"
51 char *msg2="&clients=";
54 printf("announcing server... ");
57 if(SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1)
59 fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError());
63 tcpsock=SDLNet_TCP_Open(&ip);
66 fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError());
70 temp=(char *)malloc(strlen(msg1)+strlen(name)+strlen(msg2)+10);
71 sprintf(temp,"%s%s%s%d\n",msg1,name,msg2,clients);
74 result=SDLNet_TCP_Send(tcpsock,temp,len);
76 fprintf(stderr,"SDLNet_TCP_Send: %s\n", SDLNet_GetError());
80 SDLNet_TCP_Close(tcpsock);
85 int main(int argc,char *argv[])
90 int nb_laps,network_speed,pub;
95 "usage: %s 'server_name' nb_laps network_speed (public|private)\n"
96 " server_name : the name of the server\n"
97 " nb_laps : the number of laps to complete for each race\n"
98 " network_speed : frequency of network messages (1 for fast network, 10 for slow network...)\n"
99 " private : this server will not be listed in the 'internet games'\n"
104 printf("server_name : %s\n",argv[1]);
105 printf("nb_laps : %d\n",nb_laps=atoi(argv[2]));
106 printf("network_speed : %d\n",network_speed=atoi(argv[3]));
107 printf("public : %d\n",pub=strcmp("private",argv[4]));
109 if (!zeRace_get_tracks(&tracklist)) exit(1);
113 fprintf(stderr,"SDL_Init: %s\n",SDL_GetError());
116 if (SDLNet_Init()==-1)
118 fprintf(stderr,"SDLNet_Init: %s\n",SDLNet_GetError());
122 udpsock=SDLNet_UDP_Open(atoi(PORT));
125 fprintf(stderr,"SDLNet_UDP_Open: %s\n",SDLNet_GetError());
129 packet=SDLNet_AllocPacket(1024);
132 fprintf(stderr,"SDLNet_AllocPacket: %s\n",SDLNet_GetError());
138 /* announce the server on internet if wanted */
140 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected) nb++;
141 if (pub) announce(argv[1],nb);
144 printf("loading track \"%s\"\n",tracklist->name);
145 fun=IMG_Load(tracklist->function);
147 /* reset clients variables */
148 for (i=0;i<MAX_CLIENTS;i++)
150 clients[i].lasttime=time;
151 clients[i].car.x=tracklist->x;
152 clients[i].car.y=tracklist->y;
155 clients[i].car.angle=tracklist->a*2*M_PI/360;
156 clients[i].car.speed=0;
157 clients[i].car.lap=0;
158 clients[i].car.lastcheck=0;
161 /* tell the clients */
165 *tmp++=1; /* startup countdown */
166 strcpy(tmp,tracklist->name);
168 memcpy(tmp,&time,sizeof(int));
170 memcpy(tmp,&network_speed,sizeof(int));
172 packet->len=(void *)tmp-(void *)packet->data;
173 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected)
175 packet->address=clients[i].address;
176 SDLNet_UDP_Send(udpsock,-1,packet);
179 /* wait for everybody startup */
180 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected) break;
181 if (i!=MAX_CLIENTS) SDL_Delay(5000);
190 /* read all available packets */
191 while (SDLNet_UDP_Recv(udpsock,packet))
193 /* return the local id based on the address */
194 id=lookup(packet->address);
196 /* look for type of message */
198 /*printf("%s\n",tmp);*/
200 /* new connection ? */
201 if (strcmp(tmp,"connect")==0)
203 /* allready connected ? */
204 if (id!=-1 && clients[id].connected)
206 /* should not happen */
207 printf("client %d allready connected\n",id);
210 for (i=0;i<MAX_CLIENTS;i++) if (!clients[i].connected)
212 clients[i].address=packet->address;
213 clients[i].connected=1;
214 clients[i].lasttime=time;
215 memset(&clients[i].car,0,sizeof(struct _car));
217 strcpy(clients[i].pseudo,tmp);
219 memcpy(&clients[i].car.color,tmp,sizeof(int));
220 clients[i].car.x=tracklist->x;
221 clients[i].car.y=tracklist->y;
224 clients[i].car.angle=tracklist->a*2*M_PI/360;
225 clients[i].car.speed=0;
226 clients[i].car.lap=0;
227 clients[i].car.lastcheck=0;
228 memcpy(ip,&packet->address.host,4);
229 printf("client %d connected at %d : %d.%d.%d.%d:%d (pseudo : %s, color : %d)\n",i,time,ip[0],ip[1],ip[2],ip[3],packet->address.port,clients[i].pseudo,clients[i].car.color);
233 *tmp++=0; /* no startup countdown */
234 strcpy(tmp,tracklist->name);
236 memcpy(tmp,&time,sizeof(int));
238 memcpy(tmp,&network_speed,sizeof(int));
240 packet->len=(void *)tmp-(void *)packet->data;
241 SDLNet_UDP_Send(udpsock,-1,packet);
247 /* disconnection ? */
248 if (strcmp(tmp,"disconnect")==0 && id!=-1)
250 clients[id].connected=0;
251 printf("client %d disconnected\n",id);
256 if (strcmp(tmp,"keys")==0)
258 if (id==-1 || !clients[id].connected)
260 /* should not happen */
261 printf("discarded \"keys\" message\n");
267 memcpy(&temp,tmp,sizeof(int));
269 if (clients[id].lasttime==temp)
271 /* printf("servertime = %d lasttime = %d temp = %d strlen(tmp) = %d\n",time,clients[id].lasttime,temp,strlen(tmp)); */
272 /*printf("keys = %s\n",tmp);*/
275 move_car(&clients[id].car,*tmp-'A',fun);
276 /*printf("%d = %f\n",id,clients[id].car.angle);*/
277 clients[id].lasttime++;
285 /* check for timeouts */
286 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected && clients[i].lasttime+MAX_LAG<time)
288 printf("client %d timeout at %d\n",i,time);
289 packet->address=clients[i].address;
290 strcpy(packet->data,"disconnected");
291 SDLNet_UDP_Send(udpsock,-1,packet);
292 clients[i].connected=0;
295 /* send update to clients */
296 if (time%network_speed==0) for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected)
299 strcpy(tmp,"positions");
301 memcpy(tmp,&time,sizeof(int));
302 tmp+=sizeof(int); /* for server time */
303 tmp+=sizeof(int); /* for client time */
304 tmp+=sizeof(int); /* for number of cars */
306 for (j=0;j<MAX_CLIENTS;j++) if (j!=i && clients[j].connected)
308 memcpy(tmp,&clients[j].car,sizeof(struct _car));
309 tmp+=sizeof(struct _car);
312 memcpy(packet->data+strlen("positions")+1+sizeof(int)+sizeof(int),&nb,sizeof(int));
313 packet->len=(void *)tmp-(void *)packet->data;
314 memcpy(packet->data+strlen("positions")+1+sizeof(int),&clients[i].lasttime,sizeof(int));
315 packet->address=clients[i].address;
316 SDLNet_UDP_Send(udpsock,-1,packet);
319 /* did someone finish the track ? */
320 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected && clients[i].car.lap==nb_laps) finish=1;
323 /* wait like clients */
328 /* send the top 10 screen */
330 strcpy(tmp,"finish");
332 tmp+=sizeof(int); /* space for number */
336 int best_sc=-1,best_id;
337 for (j=0;j<MAX_CLIENTS;j++) if (clients[j].connected && clients[j].car.lap*32+clients[j].car.lastcheck>best_sc)
339 best_sc=clients[j].car.lap*32+clients[j].car.lastcheck;
344 sprintf(tmp,"%s : %d",clients[best_id].pseudo,best_sc);
346 memcpy(tmp,&clients[best_id].car.color,sizeof(int));
348 clients[best_id].car.lap=-1;
350 printf("top %d : %s - %d\n",nb,clients[best_id].pseudo,best_sc);
353 memcpy(packet->data+strlen("finish")+1,&nb,sizeof(int));
354 packet->len=(void *)tmp-(void *)packet->data;
355 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected)
357 packet->address=clients[i].address;
358 SDLNet_UDP_Send(udpsock,-1,packet);
362 tracklist=tracklist->next;