5 * Copyright (C) 2003, 2007, 2008, 2009 Thomas Perl <thp@thpinfo.com>
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,
28 #include <SDL/SDL_net.h>
30 /* HELPER FUNCTIONS */
33 pack_float(float v
, float min
, float max
)
35 assert(v
>= min
&& v
< max
);
36 return (Uint32
)((1U<<31) * (v
-min
) / (max
-min
));
40 unpack_float(Uint32 v
, float min
, float max
)
43 return v
* (max
-min
) / (1U<<31) + min
;
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);
74 connection
->master
= master
;
80 network_disconnect(TennixNet
* connection
)
82 if (connection
!= NULL
)
84 SDLNet_UDP_Close(connection
->send_socket
);
85 SDLNet_UDP_Close(connection
->recv_input_socket
);
86 SDLNet_UDP_Close(connection
->recv_state_socket
);
87 SDLNet_FreePacket(connection
->input_packet
);
88 SDLNet_FreePacket(connection
->state_packet
);
94 network_send_input(TennixNet
* connection
, NetworkInputData
* src
)
97 if (connection
!= NULL
) {
98 memcpy(connection
->input_packet
->data
, src
, sizeof(NetworkInputData
));
99 connection
->input_packet
->address
.host
= connection
->peer
.host
;
100 SDLNet_Write16(connection
->base_port_remote
, &(connection
->input_packet
->address
.port
));
101 connection
->input_packet
->channel
= -1;
102 connection
->input_packet
->len
= sizeof(NetworkInputData
);
103 SDLNet_UDP_Send(connection
->send_socket
, -1, connection
->input_packet
);
108 network_send_state(TennixNet
* connection
, GameState
* src
)
111 if (connection
!= NULL
&& connection
->master
) {
112 net_serialize_gamestate(src
, (NetworkGameState
*)(connection
->state_packet
->data
));
113 connection
->state_packet
->address
.host
= connection
->peer
.host
;
114 SDLNet_Write16(connection
->base_port_remote
+1, &(connection
->state_packet
->address
.port
));
115 connection
->state_packet
->channel
= -1;
116 connection
->state_packet
->len
= sizeof(NetworkGameState
);
117 assert(SDLNet_UDP_Send(connection
->send_socket
, -1, connection
->state_packet
)!=0);
122 network_receive(TennixNet
* connection
)
124 if (connection
!= NULL
) {
125 connection
->input_packet
->len
= sizeof(NetworkInputData
);
126 while (SDLNet_UDP_Recv(connection
->recv_input_socket
, connection
->input_packet
)) {
127 connection
->input_available
= true;
130 if (!(connection
->master
)) {
131 connection
->state_packet
->len
= sizeof(NetworkGameState
);
132 while (SDLNet_UDP_Recv(connection
->recv_state_socket
, connection
->state_packet
)) {
133 connection
->state_available
= true;
140 network_get_input(TennixNet
* connection
, NetworkInputData
* dest
)
142 assert(dest
!= NULL
);
143 if (connection
!= NULL
&& connection
->input_available
) {
144 memcpy(dest
, connection
->input_packet
->data
, sizeof(NetworkInputData
));
145 connection
->input_available
= false;
150 network_get_gamestate(TennixNet
* connection
, GameState
* dest
)
152 assert(dest
!= NULL
);
153 if (connection
!= NULL
&& connection
->state_available
) {
154 net_unserialize_gamestate((NetworkGameState
*)
155 (connection
->state_packet
->data
), dest
);
156 connection
->state_available
= false;
162 net_serialize_ball(const Ball
* src
, NetworkBall
* dest
)
164 assert(src
!= NULL
&& dest
!= NULL
);
165 SDLNet_Write32(pack_float(src
->x
, -WIDTH
, WIDTH
*2), &(dest
->x
));
166 SDLNet_Write32(pack_float(src
->y
, -HEIGHT
, HEIGHT
*2), &(dest
->y
));
167 SDLNet_Write32(pack_float(src
->z
, -50, 50), &(dest
->z
));
168 SDLNet_Write32(pack_float(src
->move_x
, -50, 50), &(dest
->move_x
));
169 SDLNet_Write32(pack_float(src
->move_y
, -50, 50), &(dest
->move_y
));
170 SDLNet_Write32(pack_float(src
->move_z
, -50, 50), &(dest
->move_z
));
171 dest
->ground_hit
= src
->ground_hit
;
172 dest
->last_hit_by
= src
->last_hit_by
;
173 dest
->inhibit_gravity
= src
->inhibit_gravity
;
177 net_unserialize_ball(const NetworkBall
* src
, Ball
* dest
)
179 assert(src
!= NULL
&& dest
!= NULL
);
180 dest
->x
= unpack_float(SDLNet_Read32(&(src
->x
)), -WIDTH
, WIDTH
*2);
181 dest
->y
= unpack_float(SDLNet_Read32(&(src
->y
)), -HEIGHT
, HEIGHT
*2);
182 dest
->z
= unpack_float(SDLNet_Read32(&(src
->z
)), -50, 50);
183 dest
->move_x
= unpack_float(SDLNet_Read32(&(src
->move_x
)), -50, 50);
184 dest
->move_y
= unpack_float(SDLNet_Read32(&(src
->move_y
)), -50, 50);
185 dest
->move_z
= unpack_float(SDLNet_Read32(&(src
->move_z
)), -50, 50);
186 dest
->ground_hit
= src
->ground_hit
;
187 dest
->last_hit_by
= src
->last_hit_by
;
188 dest
->inhibit_gravity
= src
->inhibit_gravity
;
192 net_serialize_player(const Player
* src
, NetworkPlayer
* dest
)
194 assert(src
!= NULL
&& dest
!= NULL
);
195 SDLNet_Write32(pack_float(src
->x
, 0, WIDTH
*1.2), &(dest
->x
));
196 SDLNet_Write32(pack_float(src
->y
, 0, HEIGHT
*1.2), &(dest
->y
));
197 SDLNet_Write32(pack_float(src
->power
, 0, 110), &(dest
->power
));
198 dest
->use_power
= src
->use_power
;
199 dest
->score
= src
->score
;
200 dest
->desire
= src
->desire
;
201 dest
->game
= src
->game
;
202 memcpy(dest
->sets
, src
->sets
, sizeof(unsigned char)*(SETS_TO_WIN
*2));
203 SDLNet_Write32(pack_float(src
->accelerate
, 0, 200), &(dest
->accelerate
));
207 net_unserialize_player(const NetworkPlayer
* src
, Player
* dest
)
209 assert(src
!= NULL
&& dest
!= NULL
);
210 dest
->x
= unpack_float(SDLNet_Read32(&(src
->x
)), 0, WIDTH
*1.2);
211 dest
->y
= unpack_float(SDLNet_Read32(&(src
->y
)), 0, HEIGHT
*1.2);
212 dest
->power
= unpack_float(SDLNet_Read32(&(src
->power
)), 0, 110);
213 dest
->use_power
= src
->use_power
;
214 dest
->score
= src
->score
;
215 dest
->desire
= src
->desire
;
216 dest
->game
= src
->game
;
217 memcpy(dest
->sets
, src
->sets
, sizeof(unsigned char)*(SETS_TO_WIN
*2));
218 dest
->accelerate
= unpack_float(SDLNet_Read32(&(src
->accelerate
)), 0, 200);
222 net_serialize_gamestate(const GameState
* src
, NetworkGameState
* dest
)
226 assert(src
!= NULL
&& dest
!= NULL
);
228 net_serialize_ball(&(src
->ball
), &(dest
->ball
));
229 for (p
=0; p
<MAXPLAYERS
; p
++) {
230 net_serialize_player(&(src
->players
[p
]), &(dest
->players
[p
]));
232 dest
->serving_player
= src
->serving_player
;
233 dest
->referee
= src
->referee
;
234 dest
->current_set
= src
->current_set
;
235 dest
->winner
= src
->winner
;
236 dest
->sound_events
= src
->sound_events
;
237 dest
->score_event
= src
->score_event
;
238 dest
->ec_game
= src
->ec_game
;
239 dest
->ec_sets
= src
->ec_sets
;
240 dest
->status_message
= src
->status_message
;
244 net_unserialize_gamestate(const NetworkGameState
* src
, GameState
* dest
)
248 assert(src
!= NULL
&& dest
!= NULL
);
250 net_unserialize_ball(&(src
->ball
), &(dest
->ball
));
251 for (p
=0; p
<MAXPLAYERS
; p
++) {
252 net_unserialize_player(&(src
->players
[p
]), &(dest
->players
[p
]));
254 dest
->serving_player
= src
->serving_player
;
255 dest
->referee
= src
->referee
;
256 dest
->current_set
= src
->current_set
;
257 dest
->winner
= src
->winner
;
258 dest
->sound_events
= src
->sound_events
;
259 dest
->score_event
= src
->score_event
;
260 dest
->ec_game
= src
->ec_game
;
261 dest
->ec_sets
= src
->ec_sets
;
262 dest
->status_message
= src
->status_message
;