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());
81 SDLNet_TCP_Close(tcpsock);
86 int main(int argc,char *argv[])
91 int nb_laps,network_speed,pub;
96 "usage: %s 'server_name' nb_laps network_speed (public|private)\n"
97 " server_name : the name of the server\n"
98 " nb_laps : the number of laps to complete for each race\n"
99 " network_speed : frequency of network messages (1 for fast network, 10 for slow network...)\n"
100 " private : this server will not be listed in the 'internet games'\n"
105 printf("server_name : %s\n",argv[1]);
106 printf("nb_laps : %d\n",nb_laps=atoi(argv[2]));
107 printf("network_speed : %d\n",network_speed=atoi(argv[3]));
108 printf("public : %d\n",pub=strcmp("private",argv[4]));
110 if (!zeRace_get_tracks(&tracklist)) exit(1);
114 fprintf(stderr,"SDL_Init: %s\n",SDL_GetError());
117 if (SDLNet_Init()==-1)
119 fprintf(stderr,"SDLNet_Init: %s\n",SDLNet_GetError());
123 udpsock=SDLNet_UDP_Open(atoi(PORT));
126 fprintf(stderr,"SDLNet_UDP_Open: %s\n",SDLNet_GetError());
130 packet=SDLNet_AllocPacket(1024);
133 fprintf(stderr,"SDLNet_AllocPacket: %s\n",SDLNet_GetError());
139 /* announce the server on internet if wanted */
141 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected) nb++;
142 if (pub) announce(argv[1],nb);
145 printf("loading track \"%s\"\n",tracklist->name);
146 fun=IMG_Load(tracklist->function);
148 /* reset clients variables */
149 for (i=0;i<MAX_CLIENTS;i++)
151 clients[i].lasttime=time;
152 clients[i].car.x=tracklist->x;
153 clients[i].car.y=tracklist->y;
156 clients[i].car.angle=tracklist->a*2*M_PI/360;
157 clients[i].car.speed=0;
158 clients[i].car.lap=0;
159 clients[i].car.lastcheck=0;
162 /* tell the clients */
166 *tmp++=1; /* startup countdown */
167 strcpy(tmp,tracklist->name);
169 SDLNet_Write32(time,tmp);
171 SDLNet_Write32(network_speed,tmp);
173 packet->len=(void *)tmp-(void *)packet->data;
174 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected)
176 packet->address=clients[i].address;
177 SDLNet_UDP_Send(udpsock,-1,packet);
180 /* wait for everybody startup */
181 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected) break;
182 /* 5000ms for countdown, and 500ms for loading time... */
183 if (i!=MAX_CLIENTS) SDL_Delay(5500);
192 /* read all available packets */
193 while (SDLNet_UDP_Recv(udpsock,packet))
195 /* return the local id based on the address */
196 id=lookup(packet->address);
198 /* look for type of message */
200 /*printf("%s\n",tmp);*/
202 /* new connection ? */
203 if (strcmp(tmp,"connect")==0)
205 /* allready connected ? */
206 if (id!=-1 && clients[id].connected)
208 /* should not happen */
209 printf("client %d allready connected\n",id);
212 for (i=0;i<MAX_CLIENTS;i++) if (!clients[i].connected)
214 clients[i].address=packet->address;
215 clients[i].connected=1;
216 clients[i].lasttime=time;
217 memset(&clients[i].car,0,sizeof(struct _car));
219 strcpy(clients[i].pseudo,tmp);
221 clients[i].car.color=SDLNet_Read16(tmp);
222 clients[i].car.x=tracklist->x;
223 clients[i].car.y=tracklist->y;
226 clients[i].car.angle=tracklist->a*2*M_PI/360;
227 clients[i].car.speed=0;
228 clients[i].car.lap=0;
229 clients[i].car.lastcheck=0;
230 memcpy(ip,&packet->address.host,4);
231 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);
235 *tmp++=0; /* no startup countdown */
236 strcpy(tmp,tracklist->name);
238 SDLNet_Write32(time,tmp);
240 SDLNet_Write32(network_speed,tmp);
242 packet->len=(void *)tmp-(void *)packet->data;
243 SDLNet_UDP_Send(udpsock,-1,packet);
249 /* disconnection ? */
250 if (strcmp(tmp,"disconnect")==0 && id!=-1)
252 clients[id].connected=0;
253 printf("client %d disconnected\n",id);
258 if (strcmp(tmp,"keys")==0)
260 if (id==-1 || !clients[id].connected)
262 /* should not happen */
263 printf("discarded \"keys\" message\n");
269 temp=SDLNet_Read32(tmp);
271 if (clients[id].lasttime<=temp)
273 tmp+=temp-clients[id].lasttime;
274 /* printf("servertime = %d lasttime = %d temp = %d strlen(tmp) = %d\n",time,clients[id].lasttime,temp,strlen(tmp)); */
275 /*printf("keys = %s\n",tmp);*/
278 move_car(&clients[id].car,*tmp-'A',fun);
279 /*printf("%d = %f\n",id,clients[id].car.angle);*/
280 clients[id].lasttime++;
288 /* check for timeouts */
289 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected && clients[i].lasttime+MAX_LAG<time)
291 printf("client %d timeout at %d\n",i,time);
292 packet->address=clients[i].address;
293 strcpy(packet->data,"disconnected");
294 SDLNet_UDP_Send(udpsock,-1,packet);
295 clients[i].connected=0;
298 /* send update to clients */
299 if (time%network_speed==0) for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected)
302 strcpy(tmp,"positions");
304 SDLNet_Write32(time,tmp);
305 tmp+=4; /* for server time */
306 tmp+=4; /* for client time */
307 tmp+=2; /* for number of cars */
309 for (j=0;j<MAX_CLIENTS;j++) if (j!=i && clients[j].connected)
311 SDLNet_Write16(clients[j].car.x,tmp);
313 SDLNet_Write16(clients[j].car.y,tmp);
315 SDLNet_Write16(clients[j].car.angle*1000,tmp);
317 SDLNet_Write16(clients[j].car.color,tmp);
321 SDLNet_Write16(nb,packet->data+strlen("positions")+1+4+4);
322 SDLNet_Write32(clients[i].lasttime,packet->data+strlen("positions")+1+4);
323 packet->len=(void *)tmp-(void *)packet->data;
324 packet->address=clients[i].address;
325 SDLNet_UDP_Send(udpsock,-1,packet);
328 /* did someone finish the track ? */
329 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected && clients[i].car.lap==nb_laps) finish=1;
332 /* wait like clients */
337 /* send the top 10 screen */
339 strcpy(tmp,"finish");
341 tmp+=2; /* space for number */
345 int best_sc=-1,best_id;
346 for (j=0;j<MAX_CLIENTS;j++) if (clients[j].connected && clients[j].car.lap*32+clients[j].car.lastcheck>best_sc)
348 best_sc=clients[j].car.lap*32+clients[j].car.lastcheck;
353 sprintf(tmp,"%s : %d",clients[best_id].pseudo,best_sc);
355 SDLNet_Write16(clients[best_id].car.color,tmp);
357 clients[best_id].car.lap=-1;
359 printf("top %d : %s - %d\n",nb,clients[best_id].pseudo,best_sc);
362 SDLNet_Write16(nb,packet->data+strlen("finish")+1);
363 packet->len=(void *)tmp-(void *)packet->data;
364 for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected)
366 packet->address=clients[i].address;
367 SDLNet_UDP_Send(udpsock,-1,packet);
371 SDL_FreeSurface(fun);
372 tracklist=tracklist->next;