* Christmas edition *; fixed irc /os command; small cleanup in fd.c; improvements...
[ZeXOS.git] / apps / tuxanci / main.c
blobe47a03f40ef8acd0566b9b96912881f44a5c7d14
1 /*
2 * ZeX/OS
3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/socket.h>
26 #define ESC 1
28 sockaddr_in sockName; // "Jméno" soketu
29 sockaddr_in clientInfo; // Informace o klientovi
30 int sock;
31 char buf[130];
32 socklen_t addrlen;
33 unsigned tux_id;
34 char map[16];
35 unsigned map_len;
36 unsigned round;
37 unsigned players_curr;
39 typedef struct client_context {
40 struct client_context *next, *prev;
42 unsigned id;
43 char name[32];
44 unsigned status;
45 sockaddr_in clientInfo;
47 unsigned x;
48 unsigned y;
50 unsigned char position;
51 unsigned char frame;
52 unsigned char score;
53 unsigned char bonus;
55 unsigned char bonus_time;
56 unsigned char pickup_time;
58 union {
59 unsigned char simple;
60 unsigned char dual;
61 unsigned char scatter;
62 unsigned char tommy;
63 unsigned char lasser;
64 unsigned char bombball;
65 } shot;
66 } client_t;
68 client_t client_list;
70 client_t *client_new (char *buffer, unsigned len)
72 unsigned x = 0;
73 unsigned y = 0;
75 /* first find out nick name start */
76 while (x < len) {
77 if (buffer[x] == ' ')
78 y ++;
80 if (y == 2)
81 break;
83 x ++;
86 if (y != 2)
87 return 0;
89 /* jump over space character before nick name */
90 x ++;
92 /* alloc and init context */
93 client_t *client = (client_t *) malloc (sizeof (client_t));
95 if (!client)
96 return 0;
98 client->id = tux_id;
100 if ((len-x) < 32)
101 memcpy (client->name, buffer+x, len-x);
103 memcpy (&client->clientInfo, &clientInfo, addrlen);
105 client->x = 9;
106 client->y = 9;
108 /* add into list */
109 client->next = &client_list;
110 client->prev = client_list.prev;
111 client->prev->next = client;
112 client->next->prev = client;
114 /* print message on screen */
115 puts ("-> New client connected: ");
116 puts (client->name);
117 puts ("\n");
119 return client;
122 int proto_ping ()
124 sendto (sock, "ping\n", 5, 0, &clientInfo, (socklen_t *) &addrlen);
126 return 1;
129 /* newtux <tux_id> <tux_x> <tux_y> <tux_status> <tux_position> <tux_frame> <tux_score> <tux_name> <tux_gun> <tux_bonus> <tux_shot_simple> <tux_shot_dual> <tux_shot_scatter> <tux_shot_tommy> <tux_shot_lasser> <tux_shot_mine> <tux_shot_bombball> <tux_bonus_time> <tux_pickup_time> */
130 int proto_newtux (client_t *client)
132 char *str = (char *) malloc (128);
134 if (!str)
135 return 0;
137 char buf[10];
139 itoa (client->id, buf, 10);
140 unsigned id_len = strlen (buf);
142 memcpy (str, "newtux ", 7);
143 memcpy (str+7, buf, id_len);
144 memcpy (str+7+id_len, " ", 1);
146 itoa (client->x, buf, 10);
147 unsigned x_len = strlen (buf);
149 memcpy (str+8+id_len, buf, x_len);
150 memcpy (str+8+id_len+x_len, " ", 1);
152 itoa (client->y, buf, 10);
153 unsigned y_len = strlen (buf);
155 free (str);
157 return 1;
160 /* init <my_tux_id> <my_tux_x> <my_tux_y> <count_round> <arena_net_name> */
161 int proto_hello (char *buffer, unsigned len)
163 char *str = (char *) malloc (128);
165 if (!str)
166 return 0;
168 client_t *client = client_new (buffer, len);
170 if (!client)
171 return 0;
173 char buf[10];
175 itoa (tux_id, buf, 10);
177 unsigned tux_id_len = strlen (buf);
179 memcpy (str, "init ", 5);
180 memcpy (str+5, buf, tux_id_len);
182 itoa (client->x, buf, 10);
183 unsigned x_len = strlen (buf);
185 memcpy (str+5+tux_id_len, " ", 1);
186 memcpy (str+6+tux_id_len, buf, x_len);
187 memcpy (str+6+tux_id_len+x_len, " ", 1);
189 itoa (client->y, buf, 10);
190 unsigned y_len = strlen (buf);
192 memcpy (str+7+tux_id_len+x_len, buf, y_len);
193 memcpy (str+7+tux_id_len+x_len+y_len, " ", 1);
195 itoa (round, buf, 10);
196 unsigned round_len = strlen (buf);
198 memcpy (str+8+tux_id_len+x_len+y_len, buf, round_len);
199 memcpy (str+8+tux_id_len+x_len+y_len+round_len, " ", 1);
201 memcpy (str+9+tux_id_len+x_len+y_len+round_len, map, map_len);
203 str[9+tux_id_len+x_len+y_len+round_len+map_len] = '\n';
205 sendto (sock, str, 10+tux_id_len+x_len+y_len+round_len+map_len, 0, &clientInfo, &addrlen);
207 free (str);
209 puts ("-> hello ()\n");
211 /* send to new client message about currently joined players */
212 if (players_curr) {
213 client_t *c;
214 for (c = client_list.next; c != &client_list; c = c->next)
215 proto_newtux (c);
218 tux_id ++;
219 players_curr ++;
221 return 1;
224 /** HANDLER Function */
225 int proto_handler (char *buffer, unsigned len)
227 if (!strncmp (buffer, "ping", 4))
228 return proto_ping ();
229 if (!strncmp (buffer, "hello", 5))
230 return proto_hello (buffer, len);
231 //if (!strncmp (buffer, "end", 3))
232 // return proto_end (buffer, len);
234 return 1;
237 /** INIT function */
238 int init ()
240 sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
242 if (!sock)
243 return 0;
245 // Zaplníme strukturu sockaddr_in
246 // 1) Rodina protokolù
247 sockName.sin_family = AF_INET;
248 // 2) Èíslo portu, na kterém èekáme
249 sockName.sin_port = htons (2900);
251 if (bind (sock, &sockName, sizeof(sockName)) == -1) {
252 puts ("-> bind () error");
253 return 0;
256 addrlen = sizeof (clientInfo);
258 client_list.next = &client_list;
259 client_list.prev = &client_list;
261 tux_id = 0;
263 /* setup map */
264 memcpy (map, "CS", 2);
265 map_len = 2;
267 /* round start on 0 */
268 round = 0;
270 /* players count is preset to 0 */
271 players_curr = 0;
273 return 1;
276 /** MAIN LOOP */
277 int loop ()
279 /* get new packets */
280 int ret = recvfrom (sock, buf, 128, 0, &clientInfo, &addrlen);
282 /* when data are available, handle it */
283 if (ret > 0) {
284 buf[ret] = '\0';
286 proto_handler (buf, ret);
288 puts (buf);
291 return 1;
294 /** MAIN Function */
295 int main (int argc, char **argv)
297 puts ("tuxanci - game server\n");
299 if (!init ())
300 return 0;
302 while (1) {
303 if (loop () == -1)
304 break;
306 schedule ();
309 puts ("-> exit\n");
311 return 1;