]> git.xonotic.org Git - xonotic/darkplaces.git/blob - com_msg.c
physics: fix and refactor unsticking
[xonotic/darkplaces.git] / com_msg.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 Copyright (C) 2000-2020 DarkPlaces contributors
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14 See the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 */
21 // com_msg.c
22
23 #include "quakedef.h"
24
25 /*
26 ============================================================================
27
28                                         BYTE ORDER FUNCTIONS
29
30 ============================================================================
31 */
32
33 /* Casting to unsigned when shifting by 24 bits here is necessary to prevent UB
34  * caused by shifting outside the range of int on platforms where int is 32 bits.
35  */
36
37 float BuffBigFloat (const unsigned char *buffer)
38 {
39         union
40         {
41                 float f;
42                 unsigned int i;
43         }
44         u;
45         u.i = ((unsigned)buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
46         return u.f;
47 }
48
49 int BuffBigLong (const unsigned char *buffer)
50 {
51         return ((unsigned)buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
52 }
53
54 short BuffBigShort (const unsigned char *buffer)
55 {
56         return (buffer[0] << 8) | buffer[1];
57 }
58
59 float BuffLittleFloat (const unsigned char *buffer)
60 {
61         union
62         {
63                 float f;
64                 unsigned int i;
65         }
66         u;
67         u.i = ((unsigned)buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
68         return u.f;
69 }
70
71 int BuffLittleLong (const unsigned char *buffer)
72 {
73         return ((unsigned)buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
74 }
75
76 short BuffLittleShort (const unsigned char *buffer)
77 {
78         return (buffer[1] << 8) | buffer[0];
79 }
80
81 void StoreBigLong (unsigned char *buffer, unsigned int i)
82 {
83         buffer[0] = (i >> 24) & 0xFF;
84         buffer[1] = (i >> 16) & 0xFF;
85         buffer[2] = (i >>  8) & 0xFF;
86         buffer[3] = i         & 0xFF;
87 }
88
89 void StoreBigShort (unsigned char *buffer, unsigned short i)
90 {
91         buffer[0] = (i >>  8) & 0xFF;
92         buffer[1] = i         & 0xFF;
93 }
94
95 void StoreLittleLong (unsigned char *buffer, unsigned int i)
96 {
97         buffer[0] = i         & 0xFF;
98         buffer[1] = (i >>  8) & 0xFF;
99         buffer[2] = (i >> 16) & 0xFF;
100         buffer[3] = (i >> 24) & 0xFF;
101 }
102
103 void StoreLittleShort (unsigned char *buffer, unsigned short i)
104 {
105         buffer[0] = i         & 0xFF;
106         buffer[1] = (i >>  8) & 0xFF;
107 }
108
109 /*
110 ==============================================================================
111
112                         MESSAGE IO FUNCTIONS
113
114 Handles byte ordering and avoids alignment errors
115 ==============================================================================
116 */
117
118 //
119 // writing functions
120 //
121
122 void MSG_WriteChar (sizebuf_t *sb, int c)
123 {
124         unsigned char    *buf;
125
126         buf = SZ_GetSpace (sb, 1);
127         buf[0] = c;
128 }
129
130 void MSG_WriteByte (sizebuf_t *sb, int c)
131 {
132         unsigned char    *buf;
133
134         buf = SZ_GetSpace (sb, 1);
135         buf[0] = c;
136 }
137
138 void MSG_WriteShort (sizebuf_t *sb, int c)
139 {
140         unsigned char    *buf;
141
142         buf = SZ_GetSpace (sb, 2);
143         buf[0] = c&0xff;
144         buf[1] = c>>8;
145 }
146
147 void MSG_WriteLong (sizebuf_t *sb, int c)
148 {
149         unsigned char    *buf;
150
151         buf = SZ_GetSpace (sb, 4);
152         buf[0] = c&0xff;
153         buf[1] = (c>>8)&0xff;
154         buf[2] = (c>>16)&0xff;
155         buf[3] = c>>24;
156 }
157
158 void MSG_WriteFloat (sizebuf_t *sb, float f)
159 {
160         union
161         {
162                 float   f;
163                 int     l;
164         } dat;
165
166
167         dat.f = f;
168         dat.l = LittleLong (dat.l);
169
170         SZ_Write (sb, (unsigned char *)&dat.l, 4);
171 }
172
173 void MSG_WriteString (sizebuf_t *sb, const char *s)
174 {
175         if (!s || !*s)
176                 MSG_WriteChar (sb, 0);
177         else
178                 SZ_Write (sb, (unsigned char *)s, (int)strlen(s)+1);
179 }
180
181 void MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s)
182 {
183         if (s && *s)
184                 SZ_Write (sb, (unsigned char *)s, (int)strlen(s));
185 }
186
187 void MSG_WriteCoord13i (sizebuf_t *sb, float f)
188 {
189         MSG_WriteShort (sb, Q_rint(f*8));
190 }
191
192 void MSG_WriteCoord16i (sizebuf_t *sb, float f)
193 {
194         MSG_WriteShort (sb, Q_rint(f));
195 }
196
197 void MSG_WriteCoord32f (sizebuf_t *sb, float f)
198 {
199         MSG_WriteFloat (sb, f);
200 }
201
202 void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol)
203 {
204         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
205                 MSG_WriteCoord13i (sb, f);
206         else if (protocol == PROTOCOL_DARKPLACES1)
207                 MSG_WriteCoord32f (sb, f);
208         else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
209                 MSG_WriteCoord16i (sb, f);
210         else
211                 MSG_WriteCoord32f (sb, f);
212 }
213
214 void MSG_WriteVector (sizebuf_t *sb, const vec3_t v, protocolversion_t protocol)
215 {
216         MSG_WriteCoord (sb, v[0], protocol);
217         MSG_WriteCoord (sb, v[1], protocol);
218         MSG_WriteCoord (sb, v[2], protocol);
219 }
220
221 // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
222 void MSG_WriteAngle8i (sizebuf_t *sb, float f)
223 {
224         MSG_WriteByte (sb, (int)Q_rint(f*(256.0/360.0)) & 255);
225 }
226
227 void MSG_WriteAngle16i (sizebuf_t *sb, float f)
228 {
229         MSG_WriteShort (sb, (int)Q_rint(f*(65536.0/360.0)) & 65535);
230 }
231
232 void MSG_WriteAngle32f (sizebuf_t *sb, float f)
233 {
234         MSG_WriteFloat (sb, f);
235 }
236
237 void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol)
238 {
239         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD)
240                 MSG_WriteAngle8i (sb, f);
241         else
242                 MSG_WriteAngle16i (sb, f);
243 }
244
245 //
246 // reading functions
247 //
248
249 void MSG_InitReadBuffer (sizebuf_t *buf, unsigned char *data, int size)
250 {
251         memset(buf, 0, sizeof(*buf));
252         buf->data = data;
253         buf->maxsize = buf->cursize = size;
254         MSG_BeginReading(buf);
255 }
256
257 void MSG_BeginReading(sizebuf_t *sb)
258 {
259         sb->readcount = 0;
260         sb->badread = false;
261 }
262
263 int MSG_ReadLittleShort(sizebuf_t *sb)
264 {
265         if (sb->readcount+2 > sb->cursize)
266         {
267                 sb->badread = true;
268                 return -1;
269         }
270         sb->readcount += 2;
271         return (short)(sb->data[sb->readcount-2] | (sb->data[sb->readcount-1]<<8));
272 }
273
274 int MSG_ReadBigShort (sizebuf_t *sb)
275 {
276         if (sb->readcount+2 > sb->cursize)
277         {
278                 sb->badread = true;
279                 return -1;
280         }
281         sb->readcount += 2;
282         return (short)((sb->data[sb->readcount-2]<<8) + sb->data[sb->readcount-1]);
283 }
284
285 int MSG_ReadLittleLong (sizebuf_t *sb)
286 {
287         if (sb->readcount+4 > sb->cursize)
288         {
289                 sb->badread = true;
290                 return -1;
291         }
292         sb->readcount += 4;
293         return sb->data[sb->readcount-4] | (sb->data[sb->readcount-3]<<8) | (sb->data[sb->readcount-2]<<16) | ((unsigned)sb->data[sb->readcount-1]<<24);
294 }
295
296 int MSG_ReadBigLong (sizebuf_t *sb)
297 {
298         if (sb->readcount+4 > sb->cursize)
299         {
300                 sb->badread = true;
301                 return -1;
302         }
303         sb->readcount += 4;
304         return ((unsigned)sb->data[sb->readcount-4]<<24) + (sb->data[sb->readcount-3]<<16) + (sb->data[sb->readcount-2]<<8) + sb->data[sb->readcount-1];
305 }
306
307 float MSG_ReadLittleFloat (sizebuf_t *sb)
308 {
309         union
310         {
311                 float f;
312                 int l;
313         } dat;
314         if (sb->readcount+4 > sb->cursize)
315         {
316                 sb->badread = true;
317                 return -1;
318         }
319         sb->readcount += 4;
320         dat.l = sb->data[sb->readcount-4] | (sb->data[sb->readcount-3]<<8) | (sb->data[sb->readcount-2]<<16) | ((unsigned)sb->data[sb->readcount-1]<<24);
321         return dat.f;
322 }
323
324 float MSG_ReadBigFloat (sizebuf_t *sb)
325 {
326         union
327         {
328                 float f;
329                 int l;
330         } dat;
331         if (sb->readcount+4 > sb->cursize)
332         {
333                 sb->badread = true;
334                 return -1;
335         }
336         sb->readcount += 4;
337         dat.l = ((unsigned)sb->data[sb->readcount-4]<<24) | (sb->data[sb->readcount-3]<<16) | (sb->data[sb->readcount-2]<<8) | sb->data[sb->readcount-1];
338         return dat.f;
339 }
340
341 char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring)
342 {
343         size_t l = 0;
344
345         // read string into sbfer, but only store as many characters as will fit
346         // if dest buffer is full sb->readcount will still be advanced to end of message string
347         while ((string[l] = MSG_ReadByte_opt(sb)) != '\0')
348                 if (l < maxstring)
349                         ++l;
350         return string;
351 }
352 size_t MSG_ReadString_len (sizebuf_t *sb, char *string, size_t maxstring)
353 {
354         size_t l = 0;
355
356         // read string into sbfer, but only store as many characters as will fit
357         // if dest buffer is full sb->readcount will still be advanced to end of message string
358         while ((string[l] = MSG_ReadByte_opt(sb)) != '\0')
359                 if (l < maxstring)
360                         ++l;
361         return l;
362 }
363
364 size_t MSG_ReadBytes (sizebuf_t *sb, size_t numbytes, unsigned char *out)
365 {
366         size_t l = 0;
367
368         // when numbytes have been read sb->readcount won't be advanced any further
369         while (l < numbytes && !sb->badread)
370                 out[l++] = MSG_ReadByte_opt(sb);
371         return l;
372 }
373
374 float MSG_ReadCoord13i (sizebuf_t *sb)
375 {
376         return MSG_ReadLittleShort(sb) * (1.0/8.0);
377 }
378
379 float MSG_ReadCoord16i (sizebuf_t *sb)
380 {
381         return (signed short) MSG_ReadLittleShort(sb);
382 }
383
384 float MSG_ReadCoord32f (sizebuf_t *sb)
385 {
386         return MSG_ReadLittleFloat(sb);
387 }
388
389 float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol)
390 {
391         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
392                 return MSG_ReadCoord13i(sb);
393         else if (protocol == PROTOCOL_DARKPLACES1)
394                 return MSG_ReadCoord32f(sb);
395         else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
396                 return MSG_ReadCoord16i(sb);
397         else
398                 return MSG_ReadCoord32f(sb);
399 }
400
401 void MSG_ReadVector (sizebuf_t *sb, vec3_t v, protocolversion_t protocol)
402 {
403         v[0] = MSG_ReadCoord(sb, protocol);
404         v[1] = MSG_ReadCoord(sb, protocol);
405         v[2] = MSG_ReadCoord(sb, protocol);
406 }
407
408 // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
409 float MSG_ReadAngle8i (sizebuf_t *sb)
410 {
411         return (signed char) MSG_ReadByte (sb) * (360.0/256.0);
412 }
413
414 float MSG_ReadAngle16i (sizebuf_t *sb)
415 {
416         return (signed short)MSG_ReadShort (sb) * (360.0/65536.0);
417 }
418
419 float MSG_ReadAngle32f (sizebuf_t *sb)
420 {
421         return MSG_ReadFloat (sb);
422 }
423
424 float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol)
425 {
426         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD)
427                 return MSG_ReadAngle8i (sb);
428         else
429                 return MSG_ReadAngle16i (sb);
430 }