e8602305caaa2d79b91bdd1fc12d8b5255afae7e
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);
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
;
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
);
100 network_send_input(TennixNet
* connection
, NetworkInputData
* src
)
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
));
117 network_send_state(TennixNet
* connection
, GameState
* src
)
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);
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;
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;
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;
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
;
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
;
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
));
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);
231 net_serialize_gamestate(const GameState
* src
, NetworkGameState
* dest
)
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
;
253 net_unserialize_gamestate(NetworkGameState
* src
, GameState
* dest
)
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
;