e2f6aa63ace59d0f6d1bac943a6747c577cc85d0
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
, 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;
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
);
98 network_set_master(TennixNet
* connection
, bool master
)
100 connection
->master
= master
;
104 network_send_input(TennixNet
* connection
, NetworkInputData
* src
)
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
);
118 network_send_state(TennixNet
* connection
, GameState
* src
)
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);
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;
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;
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;
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
;
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
;
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
));
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);
232 net_serialize_gamestate(const GameState
* src
, NetworkGameState
* dest
)
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
;
254 net_unserialize_gamestate(const NetworkGameState
* src
, GameState
* dest
)
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
;