fixed bumpmapping! now looks correct
[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_Heartbeat (const char *master)
43 {
44 }
45
46
47 void Loop_Listen (qboolean state)
48 {
49 }
50
51
52 void Loop_SearchForHosts (qboolean xmit)
53 {
54         if (!sv.active)
55                 return;
56
57         hostCacheCount = 1;
58         if (strcmp(hostname.string, "UNNAMED") == 0)
59                 strcpy(hostcache[0].name, "local");
60         else
61                 strcpy(hostcache[0].name, hostname.string);
62         strcpy(hostcache[0].map, sv.name);
63         hostcache[0].users = net_activeconnections;
64         hostcache[0].maxusers = svs.maxclients;
65         hostcache[0].driver = net_driverlevel;
66         strcpy(hostcache[0].cname, "local");
67 }
68
69
70 qboolean Loop_SearchForInetHosts (const char *master)
71 {
72         return false;
73 }
74
75
76 qsocket_t *Loop_Connect (const char *host)
77 {
78         if (strcmp(host,"local") != 0)
79                 return NULL;
80         
81         localconnectpending = true;
82
83         if (!loop_client)
84         {
85                 if ((loop_client = NET_NewQSocket ()) == NULL)
86                 {
87                         Con_Printf("Loop_Connect: no qsocket available\n");
88                         return NULL;
89                 }
90                 strcpy (loop_client->address, "localhost");
91         }
92         loop_client->receiveMessageLength = 0;
93         loop_client->sendMessageLength = 0;
94         loop_client->canSend = true;
95
96         if (!loop_server)
97         {
98                 if ((loop_server = NET_NewQSocket ()) == NULL)
99                 {
100                         Con_Printf("Loop_Connect: no qsocket available\n");
101                         return NULL;
102                 }
103                 strcpy (loop_server->address, "LOCAL");
104         }
105         loop_server->receiveMessageLength = 0;
106         loop_server->sendMessageLength = 0;
107         loop_server->canSend = true;
108
109         loop_client->driverdata = (void *)loop_server;
110         loop_server->driverdata = (void *)loop_client;
111         
112         return loop_client;     
113 }
114
115
116 qsocket_t *Loop_CheckNewConnections (void)
117 {
118         if (!localconnectpending)
119                 return NULL;
120
121         localconnectpending = false;
122         loop_server->sendMessageLength = 0;
123         loop_server->receiveMessageLength = 0;
124         loop_server->canSend = true;
125         loop_client->sendMessageLength = 0;
126         loop_client->receiveMessageLength = 0;
127         loop_client->canSend = true;
128         return loop_server;
129 }
130
131
132 static int IntAlign(int value)
133 {
134         return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1));
135 }
136
137
138 int Loop_GetMessage (qsocket_t *sock)
139 {
140         int             ret;
141         int             length;
142
143         if (sock->receiveMessageLength == 0)
144                 return 0;
145
146         ret = sock->receiveMessage[0];
147         length = sock->receiveMessage[1] + (sock->receiveMessage[2] << 8);
148         // alignment byte skipped here
149         SZ_Clear (&net_message);
150         SZ_Write (&net_message, &sock->receiveMessage[4], length);
151
152         length = IntAlign(length + 4);
153         sock->receiveMessageLength -= length;
154
155         if (sock->receiveMessageLength)
156                 memcpy(sock->receiveMessage, &sock->receiveMessage[length], sock->receiveMessageLength);
157
158         if (sock->driverdata && ret == 1)
159                 ((qsocket_t *)sock->driverdata)->canSend = true;
160
161         return ret;
162 }
163
164
165 int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data)
166 {
167         qbyte *buffer;
168         int *bufferLength;
169
170         if (!sock->driverdata)
171                 return -1;
172
173         bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength;
174
175         if ((*bufferLength + data->cursize + 4) > NET_MAXMESSAGE)
176                 Host_Error("Loop_SendMessage: overflow\n");
177
178         buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength;
179
180         // message type
181         *buffer++ = 1;
182
183         // length
184         *buffer++ = data->cursize & 0xff;
185         *buffer++ = data->cursize >> 8;
186
187         // align
188         buffer++;
189
190         // message
191         memcpy(buffer, data->data, data->cursize);
192         *bufferLength = IntAlign(*bufferLength + data->cursize + 4);
193
194         sock->canSend = false;
195         return 1;
196 }
197
198
199 int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
200 {
201         qbyte *buffer;
202         int *bufferLength;
203
204         if (!sock->driverdata)
205                 return -1;
206
207         bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength;
208
209         // LordHavoc: added an extra sizeof(qbyte) to account for alignment
210         if ((*bufferLength + data->cursize + sizeof(qbyte) + sizeof(short) + sizeof(qbyte)) > NET_MAXMESSAGE)
211                 return 0;
212
213         buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength;
214
215         // message type
216         *buffer++ = 2;
217
218         // length
219         *buffer++ = data->cursize & 0xff;
220         *buffer++ = data->cursize >> 8;
221
222         // align
223         buffer++;
224
225         // message
226         memcpy(buffer, data->data, data->cursize);
227         *bufferLength = IntAlign(*bufferLength + data->cursize + 4);
228         return 1;
229 }
230
231
232 qboolean Loop_CanSendMessage (qsocket_t *sock)
233 {
234         if (!sock->driverdata)
235                 return false;
236         return sock->canSend;
237 }
238
239
240 qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock)
241 {
242         return true;
243 }
244
245
246 void Loop_Close (qsocket_t *sock)
247 {
248         if (sock->driverdata)
249                 ((qsocket_t *)sock->driverdata)->driverdata = NULL;
250         sock->receiveMessageLength = 0;
251         sock->sendMessageLength = 0;
252         sock->canSend = true;
253         if (sock == loop_client)
254                 loop_client = NULL;
255         else
256                 loop_server = NULL;
257 }
258