Code clean-ups and makefile optimizations
[tennix.git] / network.c
blobe8602305caaa2d79b91bdd1fc12d8b5255afae7e
2 /**
4 * Tennix! SDL Port
5 * Copyright (C) 2003, 2007, 2008, 2009 Thomas Perl <thp@thpinfo.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
22 **/
24 #include "game.h"
25 #include "network.h"
27 #include <assert.h>
28 #include <SDL/SDL_net.h>
30 /* HELPER FUNCTIONS */
32 Uint32
33 pack_float(float v, float min, float max)
35 assert(v >= min && v < max);
36 return (Uint32)((1U<<31) * (v-min) / (max-min));
39 float
40 unpack_float(Uint32 v, float min, float max)
42 assert(v < (1U<<31));
43 return v * (max-min) / (1U<<31) + min;
46 void
47 init_network()
49 SDLNet_Init();
52 void
53 uninit_network()
55 SDLNet_Quit();
58 TennixNet*
59 network_connect(const char* host, bool master)
61 TennixNet* connection = (TennixNet*)malloc(sizeof(TennixNet));
62 assert(connection != NULL);
64 assert(SDLNet_ResolveHost(&(connection->peer), (const char*)host, 0) == 0);
65 connection->base_port_local = (master)?(TENNIXNET_PORT_MASTER):(TENNIXNET_PORT_SLAVE);
66 connection->base_port_remote = (master)?(TENNIXNET_PORT_SLAVE):(TENNIXNET_PORT_MASTER);
67 connection->input_packet = SDLNet_AllocPacket(sizeof(NetworkInputData));
68 connection->state_packet = SDLNet_AllocPacket(sizeof(NetworkGameState));
69 connection->input_available = false;
70 connection->state_available = false;
71 connection->send_socket = SDLNet_UDP_Open(0);
72 connection->recv_input_socket = SDLNet_UDP_Open(connection->base_port_local);
73 connection->recv_state_socket = SDLNet_UDP_Open(connection->base_port_local+1);
75 /* Fill with invalid data for first-time update */
76 connection->input_data.x = 0xFF;
77 connection->input_data.y = 0xFF;
78 connection->input_data.keys = 0xFF;
80 connection->master = master;
82 return connection;
85 void
86 network_disconnect(TennixNet* connection)
88 if (connection != NULL)
90 SDLNet_UDP_Close(connection->send_socket);
91 SDLNet_UDP_Close(connection->recv_input_socket);
92 SDLNet_UDP_Close(connection->recv_state_socket);
93 SDLNet_FreePacket(connection->input_packet);
94 SDLNet_FreePacket(connection->state_packet);
95 free(connection);
99 void
100 network_send_input(TennixNet* connection, NetworkInputData* src)
102 assert(src != NULL);
103 if (connection != NULL && memcmp(&(connection->input_data),
104 src, sizeof(NetworkInputData)) != 0) {
105 memcpy(connection->input_packet->data, src, sizeof(NetworkInputData));
106 connection->input_packet->address.host = connection->peer.host;
107 SDLNet_Write16(connection->base_port_remote, &(connection->input_packet->address.port));
108 connection->input_packet->channel = -1;
109 connection->input_packet->len = sizeof(NetworkInputData);
110 SDLNet_UDP_Send(connection->send_socket, -1, connection->input_packet);
111 /* Remember what we sent (what the remote end "sees") right now */
112 memcpy(&(connection->input_data), src, sizeof(NetworkInputData));
116 void
117 network_send_state(TennixNet* connection, GameState* src)
119 assert(src != NULL);
120 if (connection != NULL && connection->master) {
121 net_serialize_gamestate(src, (NetworkGameState*)(connection->state_packet->data));
122 connection->state_packet->address.host = connection->peer.host;
123 SDLNet_Write16(connection->base_port_remote+1, &(connection->state_packet->address.port));
124 connection->state_packet->channel = -1;
125 connection->state_packet->len = sizeof(NetworkGameState);
126 assert(SDLNet_UDP_Send(connection->send_socket, -1, connection->state_packet)!=0);
130 void
131 network_receive(TennixNet* connection)
133 if (connection != NULL) {
134 connection->input_packet->len = sizeof(NetworkInputData);
135 while (SDLNet_UDP_Recv(connection->recv_input_socket, connection->input_packet)) {
136 connection->input_available = true;
139 if (!(connection->master)) {
140 connection->state_packet->len = sizeof(NetworkGameState);
141 while (SDLNet_UDP_Recv(connection->recv_state_socket, connection->state_packet)) {
142 connection->state_available = true;
148 void
149 network_get_input(TennixNet* connection, NetworkInputData* dest)
151 assert(dest != NULL);
152 if (connection != NULL && connection->input_available) {
153 memcpy(dest, connection->input_packet->data, sizeof(NetworkInputData));
154 connection->input_available = false;
158 void
159 network_get_gamestate(TennixNet* connection, GameState* dest)
161 assert(dest != NULL);
162 if (connection != NULL && connection->state_available) {
163 net_unserialize_gamestate((NetworkGameState*)
164 (connection->state_packet->data), dest);
165 connection->state_available = false;
170 void
171 net_serialize_ball(const Ball* src, NetworkBall* dest)
173 assert(src != NULL && dest != NULL);
174 SDLNet_Write32(pack_float(src->x, -WIDTH, WIDTH*2), &(dest->x));
175 SDLNet_Write32(pack_float(src->y, -HEIGHT, HEIGHT*2), &(dest->y));
176 SDLNet_Write32(pack_float(src->z, -50, 50), &(dest->z));
177 SDLNet_Write32(pack_float(src->move_x, -50, 50), &(dest->move_x));
178 SDLNet_Write32(pack_float(src->move_y, -50, 50), &(dest->move_y));
179 SDLNet_Write32(pack_float(src->move_z, -50, 50), &(dest->move_z));
180 dest->ground_hit = src->ground_hit;
181 dest->last_hit_by = src->last_hit_by;
182 dest->inhibit_gravity = src->inhibit_gravity;
185 void
186 net_unserialize_ball(NetworkBall* src, Ball* dest)
188 assert(src != NULL && dest != NULL);
189 dest->x = unpack_float(SDLNet_Read32(&(src->x)), -WIDTH, WIDTH*2);
190 dest->y = unpack_float(SDLNet_Read32(&(src->y)), -HEIGHT, HEIGHT*2);
191 dest->z = unpack_float(SDLNet_Read32(&(src->z)), -50, 50);
192 dest->move_x = unpack_float(SDLNet_Read32(&(src->move_x)), -50, 50);
193 dest->move_y = unpack_float(SDLNet_Read32(&(src->move_y)), -50, 50);
194 dest->move_z = unpack_float(SDLNet_Read32(&(src->move_z)), -50, 50);
195 dest->ground_hit = src->ground_hit;
196 dest->last_hit_by = src->last_hit_by;
197 dest->inhibit_gravity = src->inhibit_gravity;
200 void
201 net_serialize_player(const Player* src, NetworkPlayer* dest)
203 assert(src != NULL && dest != NULL);
204 SDLNet_Write32(pack_float(src->x, 0, WIDTH*1.2), &(dest->x));
205 SDLNet_Write32(pack_float(src->y, 0, HEIGHT*1.2), &(dest->y));
206 SDLNet_Write32(pack_float(src->power, 0, 110), &(dest->power));
207 dest->use_power = src->use_power;
208 dest->score = src->score;
209 dest->desire = src->desire;
210 dest->game = src->game;
211 memcpy(dest->sets, src->sets, sizeof(unsigned char)*(SETS_TO_WIN*2));
212 SDLNet_Write32(pack_float(src->accelerate, 0, 200), &(dest->accelerate));
215 void
216 net_unserialize_player(NetworkPlayer* src, Player* dest)
218 assert(src != NULL && dest != NULL);
219 dest->x = unpack_float(SDLNet_Read32(&(src->x)), 0, WIDTH*1.2);
220 dest->y = unpack_float(SDLNet_Read32(&(src->y)), 0, HEIGHT*1.2);
221 dest->power = unpack_float(SDLNet_Read32(&(src->power)), 0, 110);
222 dest->use_power = src->use_power;
223 dest->score = src->score;
224 dest->desire = (PlayerDesire)src->desire;
225 dest->game = src->game;
226 memcpy(dest->sets, src->sets, sizeof(unsigned char)*(SETS_TO_WIN*2));
227 dest->accelerate = unpack_float(SDLNet_Read32(&(src->accelerate)), 0, 200);
230 void
231 net_serialize_gamestate(const GameState* src, NetworkGameState* dest)
233 int p;
235 assert(src != NULL && dest != NULL);
237 net_serialize_ball(&(src->ball), &(dest->ball));
238 for (p=0; p<MAXPLAYERS; p++) {
239 net_serialize_player(&(src->players[p]), &(dest->players[p]));
241 dest->serving_player = src->serving_player;
242 dest->referee = src->referee;
243 dest->current_set = src->current_set;
244 dest->winner = src->winner;
245 dest->sound_events = src->sound_events;
246 dest->score_event = src->score_event;
247 dest->ec_game = src->ec_game;
248 dest->ec_sets = src->ec_sets;
249 dest->status_message = src->status_message;
252 void
253 net_unserialize_gamestate(NetworkGameState* src, GameState* dest)
255 int p;
257 assert(src != NULL && dest != NULL);
259 net_unserialize_ball(&(src->ball), &(dest->ball));
260 for (p=0; p<MAXPLAYERS; p++) {
261 net_unserialize_player(&(src->players[p]), &(dest->players[p]));
263 dest->serving_player = src->serving_player;
264 dest->referee = src->referee;
265 dest->current_set = src->current_set;
266 dest->winner = src->winner;
267 dest->sound_events = src->sound_events;
268 dest->score_event = src->score_event;
269 dest->ec_game = src->ec_game;
270 dest->ec_sets = src->ec_sets;
271 dest->status_message = src->status_message;