added viewzoom extension to QC and client (smooth sniper zooming, with sensitivity...
[divverent/darkplaces.git] / net_loop.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // net_loop.c
21
22 #include "quakedef.h"
23 #include "net_loop.h"
24
25 qboolean        localconnectpending = false;
26 qsocket_t       *loop_client = NULL;
27 qsocket_t       *loop_server = NULL;
28
29 int Loop_Init (void)
30 {
31         if (cls.state == ca_dedicated)
32                 return -1;
33         return 0;
34 }
35
36
37 void Loop_Shutdown (void)
38 {
39 }
40
41
42 void Loop_Listen (qboolean state)
43 {
44 }
45
46
47 void Loop_SearchForHosts (qboolean xmit)
48 {
49         if (!sv.active)
50                 return;
51
52         hostCacheCount = 1;
53         if (strcmp(hostname.string, "UNNAMED") == 0)
54                 strcpy(hostcache[0].name, "local");
55         else
56                 strcpy(hostcache[0].name, hostname.string);
57         strcpy(hostcache[0].map, sv.name);
58         hostcache[0].users = net_activeconnections;
59         hostcache[0].maxusers = svs.maxclients;
60         hostcache[0].driver = net_driverlevel;
61         strcpy(hostcache[0].cname, "local");
62 }
63
64
65 qsocket_t *Loop_Connect (char *host)
66 {
67         if (strcmp(host,"local") != 0)
68                 return NULL;
69         
70         localconnectpending = true;
71
72         if (!loop_client)
73         {
74                 if ((loop_client = NET_NewQSocket ()) == NULL)
75                 {
76                         Con_Printf("Loop_Connect: no qsocket available\n");
77                         return NULL;
78                 }
79                 strcpy (loop_client->address, "localhost");
80         }
81         loop_client->receiveMessageLength = 0;
82         loop_client->sendMessageLength = 0;
83         loop_client->canSend = true;
84
85         if (!loop_server)
86         {
87                 if ((loop_server = NET_NewQSocket ()) == NULL)
88                 {
89                         Con_Printf("Loop_Connect: no qsocket available\n");
90                         return NULL;
91                 }
92                 strcpy (loop_server->address, "LOCAL");
93         }
94         loop_server->receiveMessageLength = 0;
95         loop_server->sendMessageLength = 0;
96         loop_server->canSend = true;
97
98         loop_client->driverdata = (void *)loop_server;
99         loop_server->driverdata = (void *)loop_client;
100         
101         return loop_client;     
102 }
103
104
105 qsocket_t *Loop_CheckNewConnections (void)
106 {
107         if (!localconnectpending)
108                 return NULL;
109
110         localconnectpending = false;
111         loop_server->sendMessageLength = 0;
112         loop_server->receiveMessageLength = 0;
113         loop_server->canSend = true;
114         loop_client->sendMessageLength = 0;
115         loop_client->receiveMessageLength = 0;
116         loop_client->canSend = true;
117         return loop_server;
118 }
119
120
121 static int IntAlign(int value)
122 {
123         return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1));
124 }
125
126
127 int Loop_GetMessage (qsocket_t *sock)
128 {
129         int             ret;
130         int             length;
131
132         if (sock->receiveMessageLength == 0)
133                 return 0;
134
135         ret = sock->receiveMessage[0];
136         length = sock->receiveMessage[1] + (sock->receiveMessage[2] << 8);
137         // alignment byte skipped here
138         SZ_Clear (&net_message);
139         SZ_Write (&net_message, &sock->receiveMessage[4], length);
140
141         length = IntAlign(length + 4);
142         sock->receiveMessageLength -= length;
143
144         if (sock->receiveMessageLength)
145                 memcpy(sock->receiveMessage, &sock->receiveMessage[length], sock->receiveMessageLength);
146
147         if (sock->driverdata && ret == 1)
148                 ((qsocket_t *)sock->driverdata)->canSend = true;
149
150         return ret;
151 }
152
153
154 int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data)
155 {
156         byte *buffer;
157         int  *bufferLength;
158
159         if (!sock->driverdata)
160                 return -1;
161
162         bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength;
163
164         if ((*bufferLength + data->cursize + 4) > NET_MAXMESSAGE)
165                 Host_Error("Loop_SendMessage: overflow\n");
166
167         buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength;
168
169         // message type
170         *buffer++ = 1;
171
172         // length
173         *buffer++ = data->cursize & 0xff;
174         *buffer++ = data->cursize >> 8;
175
176         // align
177         buffer++;
178
179         // message
180         memcpy(buffer, data->data, data->cursize);
181         *bufferLength = IntAlign(*bufferLength + data->cursize + 4);
182
183         sock->canSend = false;
184         return 1;
185 }
186
187
188 int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
189 {
190         byte *buffer;
191         int  *bufferLength;
192
193         if (!sock->driverdata)
194                 return -1;
195
196         bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength;
197
198         // LordHavoc: added an extra sizeof(byte) to account for alignment
199         if ((*bufferLength + data->cursize + sizeof(byte) + sizeof(short) + sizeof(byte)) > NET_MAXMESSAGE)
200                 return 0;
201
202         buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength;
203
204         // message type
205         *buffer++ = 2;
206
207         // length
208         *buffer++ = data->cursize & 0xff;
209         *buffer++ = data->cursize >> 8;
210
211         // align
212         buffer++;
213
214         // message
215         memcpy(buffer, data->data, data->cursize);
216         *bufferLength = IntAlign(*bufferLength + data->cursize + 4);
217         return 1;
218 }
219
220
221 qboolean Loop_CanSendMessage (qsocket_t *sock)
222 {
223         if (!sock->driverdata)
224                 return false;
225         return sock->canSend;
226 }
227
228
229 qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock)
230 {
231         return true;
232 }
233
234
235 void Loop_Close (qsocket_t *sock)
236 {
237         if (sock->driverdata)
238                 ((qsocket_t *)sock->driverdata)->driverdata = NULL;
239         sock->receiveMessageLength = 0;
240         sock->sendMessageLength = 0;
241         sock->canSend = true;
242         if (sock == loop_client)
243                 loop_client = NULL;
244         else
245                 loop_server = NULL;
246 }