Add Mac OS X support for networking; better network code
[tennix.git] / network.c
blobe2f6aa63ace59d0f6d1bac943a6747c577cc85d0
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, Uint16 local_port, Uint16 remote_port)
61 TennixNet* connection = (TennixNet*)malloc(sizeof(TennixNet));
62 assert(connection != NULL);
64 fprintf(stderr, "ports: %d and %d\n", local_port, remote_port);
66 assert(SDLNet_ResolveHost(&(connection->peer), (const char*)host, 0) == 0);
67 connection->base_port_local = local_port;
68 connection->base_port_remote = remote_port;
69 connection->input_packet = SDLNet_AllocPacket(sizeof(NetworkInputData));
70 connection->state_packet = SDLNet_AllocPacket(sizeof(NetworkGameState));
71 connection->input_available = false;
72 connection->state_available = false;
73 connection->send_input_socket = SDLNet_UDP_Open(0);
74 connection->send_state_socket = SDLNet_UDP_Open(0);
75 connection->recv_input_socket = SDLNet_UDP_Open(connection->base_port_local);
76 connection->recv_state_socket = SDLNet_UDP_Open(connection->base_port_local+1);
77 connection->master = false;
79 return connection;
82 void
83 network_disconnect(TennixNet* connection)
85 if (connection != NULL)
87 SDLNet_UDP_Close(connection->send_input_socket);
88 SDLNet_UDP_Close(connection->send_state_socket);
89 SDLNet_UDP_Close(connection->recv_input_socket);
90 SDLNet_UDP_Close(connection->recv_state_socket);
91 SDLNet_FreePacket(connection->input_packet);
92 SDLNet_FreePacket(connection->state_packet);
93 free(connection);
97 void
98 network_set_master(TennixNet* connection, bool master)
100 connection->master = master;
103 void
104 network_send_input(TennixNet* connection, NetworkInputData* src)
106 assert(src != NULL);
107 if (connection != NULL) {
108 memcpy(connection->input_packet->data, src, sizeof(NetworkInputData));
109 connection->input_packet->address.host = connection->peer.host;
110 SDLNet_Write16(connection->base_port_remote, &(connection->input_packet->address.port));
111 connection->input_packet->channel = -1;
112 connection->input_packet->len = sizeof(NetworkInputData);
113 SDLNet_UDP_Send(connection->send_input_socket, -1, connection->input_packet);
117 void
118 network_send_state(TennixNet* connection, GameState* src)
120 assert(src != NULL);
121 if (connection != NULL && connection->master) {
122 net_serialize_gamestate(src, (NetworkGameState*)(connection->state_packet->data));
123 connection->state_packet->address.host = connection->peer.host;
124 SDLNet_Write16(connection->base_port_remote+1, &(connection->state_packet->address.port));
125 connection->state_packet->channel = -1;
126 connection->state_packet->len = sizeof(NetworkGameState);
127 assert(SDLNet_UDP_Send(connection->send_state_socket, -1, connection->state_packet)!=0);
131 void
132 network_receive(TennixNet* connection)
134 if (connection != NULL) {
135 connection->input_packet->len = sizeof(NetworkInputData);
136 while (SDLNet_UDP_Recv(connection->recv_input_socket, connection->input_packet)) {
137 connection->input_available = true;
140 if (!(connection->master)) {
141 connection->state_packet->len = sizeof(NetworkGameState);
142 while (SDLNet_UDP_Recv(connection->recv_state_socket, connection->state_packet)) {
143 connection->state_available = true;
149 void
150 network_get_input(TennixNet* connection, NetworkInputData* dest)
152 assert(dest != NULL);
153 if (connection != NULL && connection->input_available) {
154 memcpy(dest, connection->input_packet->data, sizeof(NetworkInputData));
155 connection->input_available = false;
159 void
160 network_get_gamestate(TennixNet* connection, GameState* dest)
162 assert(dest != NULL);
163 if (connection != NULL && connection->state_available) {
164 net_unserialize_gamestate((NetworkGameState*)
165 (connection->state_packet->data), dest);
166 connection->state_available = false;
171 void
172 net_serialize_ball(const Ball* src, NetworkBall* dest)
174 assert(src != NULL && dest != NULL);
175 SDLNet_Write32(pack_float(src->x, -WIDTH, WIDTH*2), &(dest->x));
176 SDLNet_Write32(pack_float(src->y, -HEIGHT, HEIGHT*2), &(dest->y));
177 SDLNet_Write32(pack_float(src->z, -50, 50), &(dest->z));
178 SDLNet_Write32(pack_float(src->move_x, -50, 50), &(dest->move_x));
179 SDLNet_Write32(pack_float(src->move_y, -50, 50), &(dest->move_y));
180 SDLNet_Write32(pack_float(src->move_z, -50, 50), &(dest->move_z));
181 dest->ground_hit = src->ground_hit;
182 dest->last_hit_by = src->last_hit_by;
183 dest->inhibit_gravity = src->inhibit_gravity;
186 void
187 net_unserialize_ball(const NetworkBall* src, Ball* dest)
189 assert(src != NULL && dest != NULL);
190 dest->x = unpack_float(SDLNet_Read32(&(src->x)), -WIDTH, WIDTH*2);
191 dest->y = unpack_float(SDLNet_Read32(&(src->y)), -HEIGHT, HEIGHT*2);
192 dest->z = unpack_float(SDLNet_Read32(&(src->z)), -50, 50);
193 dest->move_x = unpack_float(SDLNet_Read32(&(src->move_x)), -50, 50);
194 dest->move_y = unpack_float(SDLNet_Read32(&(src->move_y)), -50, 50);
195 dest->move_z = unpack_float(SDLNet_Read32(&(src->move_z)), -50, 50);
196 dest->ground_hit = src->ground_hit;
197 dest->last_hit_by = src->last_hit_by;
198 dest->inhibit_gravity = src->inhibit_gravity;
201 void
202 net_serialize_player(const Player* src, NetworkPlayer* dest)
204 assert(src != NULL && dest != NULL);
205 SDLNet_Write32(pack_float(src->x, 0, WIDTH*1.2), &(dest->x));
206 SDLNet_Write32(pack_float(src->y, 0, HEIGHT*1.2), &(dest->y));
207 SDLNet_Write32(pack_float(src->power, 0, 110), &(dest->power));
208 dest->use_power = src->use_power;
209 dest->score = src->score;
210 dest->desire = src->desire;
211 dest->game = src->game;
212 memcpy(dest->sets, src->sets, sizeof(unsigned char)*(SETS_TO_WIN*2));
213 SDLNet_Write32(pack_float(src->accelerate, 0, 200), &(dest->accelerate));
216 void
217 net_unserialize_player(const NetworkPlayer* src, Player* dest)
219 assert(src != NULL && dest != NULL);
220 dest->x = unpack_float(SDLNet_Read32(&(src->x)), 0, WIDTH*1.2);
221 dest->y = unpack_float(SDLNet_Read32(&(src->y)), 0, HEIGHT*1.2);
222 dest->power = unpack_float(SDLNet_Read32(&(src->power)), 0, 110);
223 dest->use_power = src->use_power;
224 dest->score = src->score;
225 dest->desire = src->desire;
226 dest->game = src->game;
227 memcpy(dest->sets, src->sets, sizeof(unsigned char)*(SETS_TO_WIN*2));
228 dest->accelerate = unpack_float(SDLNet_Read32(&(src->accelerate)), 0, 200);
231 void
232 net_serialize_gamestate(const GameState* src, NetworkGameState* dest)
234 int p;
236 assert(src != NULL && dest != NULL);
238 net_serialize_ball(&(src->ball), &(dest->ball));
239 for (p=0; p<MAXPLAYERS; p++) {
240 net_serialize_player(&(src->players[p]), &(dest->players[p]));
242 dest->serving_player = src->serving_player;
243 dest->referee = src->referee;
244 dest->current_set = src->current_set;
245 dest->winner = src->winner;
246 dest->sound_events = src->sound_events;
247 dest->score_event = src->score_event;
248 dest->ec_game = src->ec_game;
249 dest->ec_sets = src->ec_sets;
250 dest->status_message = src->status_message;
253 void
254 net_unserialize_gamestate(const NetworkGameState* src, GameState* dest)
256 int p;
258 assert(src != NULL && dest != NULL);
260 net_unserialize_ball(&(src->ball), &(dest->ball));
261 for (p=0; p<MAXPLAYERS; p++) {
262 net_unserialize_player(&(src->players[p]), &(dest->players[p]));
264 dest->serving_player = src->serving_player;
265 dest->referee = src->referee;
266 dest->current_set = src->current_set;
267 dest->winner = src->winner;
268 dest->sound_events = src->sound_events;
269 dest->score_event = src->score_event;
270 dest->ec_game = src->ec_game;
271 dest->ec_sets = src->ec_sets;
272 dest->status_message = src->status_message;