1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 
5 This file is part of Quake III Arena source code.
6 
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, 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.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 
23 #include "client.h"
24 
25 #include "../botlib/botlib.h"
26 
27 extern	botlib_export_t	*botlib_export;
28 
29 vm_t *uivm;
30 
31 /*
32 ====================
33 GetClientState
34 ====================
35 */
GetClientState(uiClientState_t * state)36 static void GetClientState( uiClientState_t *state ) {
37 	state->connectPacketCount = clc.connectPacketCount;
38 	state->connState = cls.state;
39 	Q_strncpyz( state->servername, cls.servername, sizeof( state->servername ) );
40 	Q_strncpyz( state->updateInfoString, cls.updateInfoString, sizeof( state->updateInfoString ) );
41 	Q_strncpyz( state->messageString, clc.serverMessage, sizeof( state->messageString ) );
42 	state->clientNum = cl.snap.ps.clientNum;
43 }
44 
45 /*
46 ====================
47 LAN_LoadCachedServers
48 ====================
49 */
LAN_LoadCachedServers(void)50 void LAN_LoadCachedServers( void ) {
51 	int size;
52 	fileHandle_t fileIn;
53 	cls.numglobalservers = cls.numfavoriteservers = 0;
54 	cls.numGlobalServerAddresses = 0;
55 	if (FS_SV_FOpenFileRead("servercache.dat", &fileIn)) {
56 		FS_Read(&cls.numglobalservers, sizeof(int), fileIn);
57 		FS_Read(&cls.numfavoriteservers, sizeof(int), fileIn);
58 		FS_Read(&size, sizeof(int), fileIn);
59 		if (size == sizeof(cls.globalServers) + sizeof(cls.favoriteServers)) {
60 			FS_Read(&cls.globalServers, sizeof(cls.globalServers), fileIn);
61 			FS_Read(&cls.favoriteServers, sizeof(cls.favoriteServers), fileIn);
62 		} else {
63 			cls.numglobalservers = cls.numfavoriteservers = 0;
64 			cls.numGlobalServerAddresses = 0;
65 		}
66 		FS_FCloseFile(fileIn);
67 	}
68 }
69 
70 /*
71 ====================
72 LAN_SaveServersToCache
73 ====================
74 */
LAN_SaveServersToCache(void)75 void LAN_SaveServersToCache( void ) {
76 	int size;
77 	fileHandle_t fileOut = FS_SV_FOpenFileWrite("servercache.dat");
78 	FS_Write(&cls.numglobalservers, sizeof(int), fileOut);
79 	FS_Write(&cls.numfavoriteservers, sizeof(int), fileOut);
80 	size = sizeof(cls.globalServers) + sizeof(cls.favoriteServers);
81 	FS_Write(&size, sizeof(int), fileOut);
82 	FS_Write(&cls.globalServers, sizeof(cls.globalServers), fileOut);
83 	FS_Write(&cls.favoriteServers, sizeof(cls.favoriteServers), fileOut);
84 	FS_FCloseFile(fileOut);
85 }
86 
87 
88 /*
89 ====================
90 LAN_ResetPings
91 ====================
92 */
LAN_ResetPings(int source)93 static void LAN_ResetPings(int source) {
94 	int count,i;
95 	serverInfo_t *servers = NULL;
96 	count = 0;
97 
98 	switch (source) {
99 		case AS_LOCAL :
100 			servers = &cls.localServers[0];
101 			count = MAX_OTHER_SERVERS;
102 			break;
103 		case AS_MPLAYER:
104 		case AS_GLOBAL :
105 			servers = &cls.globalServers[0];
106 			count = MAX_GLOBAL_SERVERS;
107 			break;
108 		case AS_FAVORITES :
109 			servers = &cls.favoriteServers[0];
110 			count = MAX_OTHER_SERVERS;
111 			break;
112 	}
113 	if (servers) {
114 		for (i = 0; i < count; i++) {
115 			servers[i].ping = -1;
116 		}
117 	}
118 }
119 
120 /*
121 ====================
122 LAN_AddServer
123 ====================
124 */
LAN_AddServer(int source,const char * name,const char * address)125 static int LAN_AddServer(int source, const char *name, const char *address) {
126 	int max, *count, i;
127 	netadr_t adr;
128 	serverInfo_t *servers = NULL;
129 	max = MAX_OTHER_SERVERS;
130 	count = NULL;
131 
132 	switch (source) {
133 		case AS_LOCAL :
134 			count = &cls.numlocalservers;
135 			servers = &cls.localServers[0];
136 			break;
137 		case AS_MPLAYER:
138 		case AS_GLOBAL :
139 			max = MAX_GLOBAL_SERVERS;
140 			count = &cls.numglobalservers;
141 			servers = &cls.globalServers[0];
142 			break;
143 		case AS_FAVORITES :
144 			count = &cls.numfavoriteservers;
145 			servers = &cls.favoriteServers[0];
146 			break;
147 	}
148 	if (servers && *count < max) {
149 		NET_StringToAdr( address, &adr, NA_IP );
150 		for ( i = 0; i < *count; i++ ) {
151 			if (NET_CompareAdr(servers[i].adr, adr)) {
152 				break;
153 			}
154 		}
155 		if (i >= *count) {
156 			servers[*count].adr = adr;
157 			Q_strncpyz(servers[*count].hostName, name, sizeof(servers[*count].hostName));
158 			servers[*count].visible = qtrue;
159 			(*count)++;
160 			return 1;
161 		}
162 		return 0;
163 	}
164 	return -1;
165 }
166 
167 /*
168 ====================
169 LAN_RemoveServer
170 ====================
171 */
LAN_RemoveServer(int source,const char * addr)172 static void LAN_RemoveServer(int source, const char *addr) {
173 	int *count, i;
174 	serverInfo_t *servers = NULL;
175 	count = NULL;
176 	switch (source) {
177 		case AS_LOCAL :
178 			count = &cls.numlocalservers;
179 			servers = &cls.localServers[0];
180 			break;
181 		case AS_MPLAYER:
182 		case AS_GLOBAL :
183 			count = &cls.numglobalservers;
184 			servers = &cls.globalServers[0];
185 			break;
186 		case AS_FAVORITES :
187 			count = &cls.numfavoriteservers;
188 			servers = &cls.favoriteServers[0];
189 			break;
190 	}
191 	if (servers) {
192 		netadr_t comp;
193 		NET_StringToAdr( addr, &comp, NA_IP );
194 		for (i = 0; i < *count; i++) {
195 			if (NET_CompareAdr( comp, servers[i].adr)) {
196 				int j = i;
197 				while (j < *count - 1) {
198 					Com_Memcpy(&servers[j], &servers[j+1], sizeof(servers[j]));
199 					j++;
200 				}
201 				(*count)--;
202 				break;
203 			}
204 		}
205 	}
206 }
207 
208 
209 /*
210 ====================
211 LAN_GetServerCount
212 ====================
213 */
LAN_GetServerCount(int source)214 static int LAN_GetServerCount( int source ) {
215 	switch (source) {
216 		case AS_LOCAL :
217 			return cls.numlocalservers;
218 			break;
219 		case AS_MPLAYER:
220 		case AS_GLOBAL :
221 			return cls.numglobalservers;
222 			break;
223 		case AS_FAVORITES :
224 			return cls.numfavoriteservers;
225 			break;
226 	}
227 	return 0;
228 }
229 
230 /*
231 ====================
232 LAN_GetLocalServerAddressString
233 ====================
234 */
LAN_GetServerAddressString(int source,int n,char * buf,int buflen)235 static void LAN_GetServerAddressString( int source, int n, char *buf, int buflen ) {
236 	switch (source) {
237 		case AS_LOCAL :
238 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
239 				Q_strncpyz(buf, NET_AdrToStringwPort( cls.localServers[n].adr) , buflen );
240 				return;
241 			}
242 			break;
243 		case AS_MPLAYER:
244 		case AS_GLOBAL :
245 			if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
246 				Q_strncpyz(buf, NET_AdrToStringwPort( cls.globalServers[n].adr) , buflen );
247 				return;
248 			}
249 			break;
250 		case AS_FAVORITES :
251 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
252 				Q_strncpyz(buf, NET_AdrToStringwPort( cls.favoriteServers[n].adr) , buflen );
253 				return;
254 			}
255 			break;
256 	}
257 	buf[0] = '\0';
258 }
259 
260 /*
261 ====================
262 LAN_GetServerInfo
263 ====================
264 */
LAN_GetServerInfo(int source,int n,char * buf,int buflen)265 static void LAN_GetServerInfo( int source, int n, char *buf, int buflen ) {
266 	char info[MAX_STRING_CHARS];
267 	serverInfo_t *server = NULL;
268 	info[0] = '\0';
269 	switch (source) {
270 		case AS_LOCAL :
271 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
272 				server = &cls.localServers[n];
273 			}
274 			break;
275 		case AS_MPLAYER:
276 		case AS_GLOBAL :
277 			if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
278 				server = &cls.globalServers[n];
279 			}
280 			break;
281 		case AS_FAVORITES :
282 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
283 				server = &cls.favoriteServers[n];
284 			}
285 			break;
286 	}
287 	if (server && buf) {
288 		buf[0] = '\0';
289 		Info_SetValueForKey( info, "hostname", server->hostName);
290 		Info_SetValueForKey( info, "mapname", server->mapName);
291 		Info_SetValueForKey( info, "clients", va("%i",server->clients));
292 		Info_SetValueForKey( info, "sv_maxclients", va("%i",server->maxClients));
293 		Info_SetValueForKey( info, "ping", va("%i",server->ping));
294 		Info_SetValueForKey( info, "minping", va("%i",server->minPing));
295 		Info_SetValueForKey( info, "maxping", va("%i",server->maxPing));
296 		Info_SetValueForKey( info, "game", server->game);
297 		Info_SetValueForKey( info, "gametype", va("%i",server->gameType));
298 		Info_SetValueForKey( info, "nettype", va("%i",server->netType));
299 		Info_SetValueForKey( info, "addr", NET_AdrToString(server->adr));
300 		Info_SetValueForKey( info, "punkbuster", va("%i", server->punkbuster));
301 		Q_strncpyz(buf, info, buflen);
302 	} else {
303 		if (buf) {
304 			buf[0] = '\0';
305 		}
306 	}
307 }
308 
309 /*
310 ====================
311 LAN_GetServerPing
312 ====================
313 */
LAN_GetServerPing(int source,int n)314 static int LAN_GetServerPing( int source, int n ) {
315 	serverInfo_t *server = NULL;
316 	switch (source) {
317 		case AS_LOCAL :
318 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
319 				server = &cls.localServers[n];
320 			}
321 			break;
322 		case AS_MPLAYER:
323 		case AS_GLOBAL :
324 			if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
325 				server = &cls.globalServers[n];
326 			}
327 			break;
328 		case AS_FAVORITES :
329 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
330 				server = &cls.favoriteServers[n];
331 			}
332 			break;
333 	}
334 	if (server) {
335 		return server->ping;
336 	}
337 	return -1;
338 }
339 
340 /*
341 ====================
342 LAN_GetServerPtr
343 ====================
344 */
LAN_GetServerPtr(int source,int n)345 static serverInfo_t *LAN_GetServerPtr( int source, int n ) {
346 	switch (source) {
347 		case AS_LOCAL :
348 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
349 				return &cls.localServers[n];
350 			}
351 			break;
352 		case AS_MPLAYER:
353 		case AS_GLOBAL :
354 			if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
355 				return &cls.globalServers[n];
356 			}
357 			break;
358 		case AS_FAVORITES :
359 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
360 				return &cls.favoriteServers[n];
361 			}
362 			break;
363 	}
364 	return NULL;
365 }
366 
367 /*
368 ====================
369 LAN_CompareServers
370 ====================
371 */
LAN_CompareServers(int source,int sortKey,int sortDir,int s1,int s2)372 static int LAN_CompareServers( int source, int sortKey, int sortDir, int s1, int s2 ) {
373 	int res;
374 	serverInfo_t *server1, *server2;
375 
376 	server1 = LAN_GetServerPtr(source, s1);
377 	server2 = LAN_GetServerPtr(source, s2);
378 	if (!server1 || !server2) {
379 		return 0;
380 	}
381 
382 	res = 0;
383 	switch( sortKey ) {
384 		case SORT_HOST:
385 			res = Q_stricmp( server1->hostName, server2->hostName );
386 			break;
387 
388 		case SORT_MAP:
389 			res = Q_stricmp( server1->mapName, server2->mapName );
390 			break;
391 		case SORT_CLIENTS:
392 			if (server1->clients < server2->clients) {
393 				res = -1;
394 			}
395 			else if (server1->clients > server2->clients) {
396 				res = 1;
397 			}
398 			else {
399 				res = 0;
400 			}
401 			break;
402 		case SORT_GAME:
403 			if (server1->gameType < server2->gameType) {
404 				res = -1;
405 			}
406 			else if (server1->gameType > server2->gameType) {
407 				res = 1;
408 			}
409 			else {
410 				res = 0;
411 			}
412 			break;
413 		case SORT_PING:
414 			if (server1->ping < server2->ping) {
415 				res = -1;
416 			}
417 			else if (server1->ping > server2->ping) {
418 				res = 1;
419 			}
420 			else {
421 				res = 0;
422 			}
423 			break;
424 	}
425 
426 	if (sortDir) {
427 		if (res < 0)
428 			return 1;
429 		if (res > 0)
430 			return -1;
431 		return 0;
432 	}
433 	return res;
434 }
435 
436 /*
437 ====================
438 LAN_GetPingQueueCount
439 ====================
440 */
LAN_GetPingQueueCount(void)441 static int LAN_GetPingQueueCount( void ) {
442 	return (CL_GetPingQueueCount());
443 }
444 
445 /*
446 ====================
447 LAN_ClearPing
448 ====================
449 */
LAN_ClearPing(int n)450 static void LAN_ClearPing( int n ) {
451 	CL_ClearPing( n );
452 }
453 
454 /*
455 ====================
456 LAN_GetPing
457 ====================
458 */
LAN_GetPing(int n,char * buf,int buflen,int * pingtime)459 static void LAN_GetPing( int n, char *buf, int buflen, int *pingtime ) {
460 	CL_GetPing( n, buf, buflen, pingtime );
461 }
462 
463 /*
464 ====================
465 LAN_GetPingInfo
466 ====================
467 */
LAN_GetPingInfo(int n,char * buf,int buflen)468 static void LAN_GetPingInfo( int n, char *buf, int buflen ) {
469 	CL_GetPingInfo( n, buf, buflen );
470 }
471 
472 /*
473 ====================
474 LAN_MarkServerVisible
475 ====================
476 */
LAN_MarkServerVisible(int source,int n,qboolean visible)477 static void LAN_MarkServerVisible(int source, int n, qboolean visible ) {
478 	if (n == -1) {
479 		int count = MAX_OTHER_SERVERS;
480 		serverInfo_t *server = NULL;
481 		switch (source) {
482 			case AS_LOCAL :
483 				server = &cls.localServers[0];
484 				break;
485 			case AS_MPLAYER:
486 			case AS_GLOBAL :
487 				server = &cls.globalServers[0];
488 				count = MAX_GLOBAL_SERVERS;
489 				break;
490 			case AS_FAVORITES :
491 				server = &cls.favoriteServers[0];
492 				break;
493 		}
494 		if (server) {
495 			for (n = 0; n < count; n++) {
496 				server[n].visible = visible;
497 			}
498 		}
499 
500 	} else {
501 		switch (source) {
502 			case AS_LOCAL :
503 				if (n >= 0 && n < MAX_OTHER_SERVERS) {
504 					cls.localServers[n].visible = visible;
505 				}
506 				break;
507 			case AS_MPLAYER:
508 			case AS_GLOBAL :
509 				if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
510 					cls.globalServers[n].visible = visible;
511 				}
512 				break;
513 			case AS_FAVORITES :
514 				if (n >= 0 && n < MAX_OTHER_SERVERS) {
515 					cls.favoriteServers[n].visible = visible;
516 				}
517 				break;
518 		}
519 	}
520 }
521 
522 
523 /*
524 =======================
525 LAN_ServerIsVisible
526 =======================
527 */
LAN_ServerIsVisible(int source,int n)528 static int LAN_ServerIsVisible(int source, int n ) {
529 	switch (source) {
530 		case AS_LOCAL :
531 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
532 				return cls.localServers[n].visible;
533 			}
534 			break;
535 		case AS_MPLAYER:
536 		case AS_GLOBAL :
537 			if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
538 				return cls.globalServers[n].visible;
539 			}
540 			break;
541 		case AS_FAVORITES :
542 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
543 				return cls.favoriteServers[n].visible;
544 			}
545 			break;
546 	}
547 	return qfalse;
548 }
549 
550 /*
551 =======================
552 LAN_UpdateVisiblePings
553 =======================
554 */
LAN_UpdateVisiblePings(int source)555 qboolean LAN_UpdateVisiblePings(int source ) {
556 	return CL_UpdateVisiblePings_f(source);
557 }
558 
559 /*
560 ====================
561 LAN_GetServerStatus
562 ====================
563 */
LAN_GetServerStatus(char * serverAddress,char * serverStatus,int maxLen)564 int LAN_GetServerStatus( char *serverAddress, char *serverStatus, int maxLen ) {
565 	return CL_ServerStatus( serverAddress, serverStatus, maxLen );
566 }
567 
568 /*
569 ====================
570 CL_GetGlConfig
571 ====================
572 */
CL_GetGlconfig(glConfig_t * config)573 static void CL_GetGlconfig( glConfig_t *config ) {
574 	*config = cls.glconfig;
575 }
576 
577 /*
578 ====================
579 CL_GetClipboardData
580 ====================
581 */
CL_GetClipboardData(char * buf,int buflen)582 static void CL_GetClipboardData( char *buf, int buflen ) {
583 	char	*cbd;
584 
585 	cbd = Sys_GetClipboardData();
586 
587 	if ( !cbd ) {
588 		*buf = 0;
589 		return;
590 	}
591 
592 	Q_strncpyz( buf, cbd, buflen );
593 
594 	Z_Free( cbd );
595 }
596 
597 /*
598 ====================
599 Key_KeynumToStringBuf
600 ====================
601 */
Key_KeynumToStringBuf(int keynum,char * buf,int buflen)602 static void Key_KeynumToStringBuf( int keynum, char *buf, int buflen ) {
603 	Q_strncpyz( buf, Key_KeynumToString( keynum ), buflen );
604 }
605 
606 /*
607 ====================
608 Key_GetBindingBuf
609 ====================
610 */
Key_GetBindingBuf(int keynum,char * buf,int buflen)611 static void Key_GetBindingBuf( int keynum, char *buf, int buflen ) {
612 	char	*value;
613 
614 	value = Key_GetBinding( keynum );
615 	if ( value ) {
616 		Q_strncpyz( buf, value, buflen );
617 	}
618 	else {
619 		*buf = 0;
620 	}
621 }
622 
623 /*
624 ====================
625 CLUI_GetCDKey
626 ====================
627 */
628 #ifndef STANDALONE
CLUI_GetCDKey(char * buf,int buflen)629 static void CLUI_GetCDKey( char *buf, int buflen ) {
630 	cvar_t	*fs;
631 	fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
632 	if (UI_usesUniqueCDKey() && fs && fs->string[0] != 0) {
633 		Com_Memcpy( buf, &cl_cdkey[16], 16);
634 		buf[16] = 0;
635 	} else {
636 		Com_Memcpy( buf, cl_cdkey, 16);
637 		buf[16] = 0;
638 	}
639 }
640 
641 
642 /*
643 ====================
644 CLUI_SetCDKey
645 ====================
646 */
CLUI_SetCDKey(char * buf)647 static void CLUI_SetCDKey( char *buf ) {
648 	cvar_t	*fs;
649 	fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
650 	if (UI_usesUniqueCDKey() && fs && fs->string[0] != 0) {
651 		Com_Memcpy( &cl_cdkey[16], buf, 16 );
652 		cl_cdkey[32] = 0;
653 		// set the flag so the fle will be written at the next opportunity
654 		cvar_modifiedFlags |= CVAR_ARCHIVE;
655 	} else {
656 		Com_Memcpy( cl_cdkey, buf, 16 );
657 		// set the flag so the fle will be written at the next opportunity
658 		cvar_modifiedFlags |= CVAR_ARCHIVE;
659 	}
660 }
661 #endif
662 
663 /*
664 ====================
665 GetConfigString
666 ====================
667 */
GetConfigString(int index,char * buf,int size)668 static int GetConfigString(int index, char *buf, int size)
669 {
670 	int		offset;
671 
672 	if (index < 0 || index >= MAX_CONFIGSTRINGS)
673 		return qfalse;
674 
675 	offset = cl.gameState.stringOffsets[index];
676 	if (!offset) {
677 		if( size ) {
678 			buf[0] = 0;
679 		}
680 		return qfalse;
681 	}
682 
683 	Q_strncpyz( buf, cl.gameState.stringData+offset, size);
684 
685 	return qtrue;
686 }
687 
688 /*
689 ====================
690 FloatAsInt
691 ====================
692 */
FloatAsInt(float f)693 static int FloatAsInt( float f ) {
694 	int		temp;
695 
696 	*(float *)&temp = f;
697 
698 	return temp;
699 }
700 
701 /*
702 ====================
703 CL_UISystemCalls
704 
705 The ui module is making a system call
706 ====================
707 */
CL_UISystemCalls(intptr_t * args)708 intptr_t CL_UISystemCalls( intptr_t *args ) {
709 	switch( args[0] ) {
710 	case UI_ERROR:
711 		Com_Error( ERR_DROP, "%s", (const char*)VMA(1) );
712 		return 0;
713 
714 	case UI_PRINT:
715 		Com_Printf( "%s", (const char*)VMA(1) );
716 		return 0;
717 
718 	case UI_MILLISECONDS:
719 		return Sys_Milliseconds();
720 
721 	case UI_CVAR_REGISTER:
722 		Cvar_Register( VMA(1), VMA(2), VMA(3), args[4] );
723 		return 0;
724 
725 	case UI_CVAR_UPDATE:
726 		Cvar_Update( VMA(1) );
727 		return 0;
728 
729 	case UI_CVAR_SET:
730 		Cvar_Set( VMA(1), VMA(2) );
731 		return 0;
732 
733 	case UI_CVAR_VARIABLEVALUE:
734 		return FloatAsInt( Cvar_VariableValue( VMA(1) ) );
735 
736 	case UI_CVAR_VARIABLESTRINGBUFFER:
737 		Cvar_VariableStringBuffer( VMA(1), VMA(2), args[3] );
738 		return 0;
739 
740 	case UI_CVAR_SETVALUE:
741 		Cvar_SetValue( VMA(1), VMF(2) );
742 		return 0;
743 
744 	case UI_CVAR_RESET:
745 		Cvar_Reset( VMA(1) );
746 		return 0;
747 
748 	case UI_CVAR_CREATE:
749 		Cvar_Get( VMA(1), VMA(2), args[3] );
750 		return 0;
751 
752 	case UI_CVAR_INFOSTRINGBUFFER:
753 		Cvar_InfoStringBuffer( args[1], VMA(2), args[3] );
754 		return 0;
755 
756 	case UI_ARGC:
757 		return Cmd_Argc();
758 
759 	case UI_ARGV:
760 		Cmd_ArgvBuffer( args[1], VMA(2), args[3] );
761 		return 0;
762 
763 	case UI_CMD_EXECUTETEXT:
764 		if(args[1] == 0
765 		&& (!strncmp(VMA(2), "snd_restart", 11)
766 		|| !strncmp(VMA(2), "vid_restart", 11)
767 		|| !strncmp(VMA(2), "quit", 5)))
768 		{
769 			Com_Printf (S_COLOR_YELLOW "turning EXEC_NOW '%.11s' into EXEC_INSERT\n", (const char*)VMA(2));
770 			args[1] = EXEC_INSERT;
771 		}
772 		Cbuf_ExecuteText( args[1], VMA(2) );
773 		return 0;
774 
775 	case UI_FS_FOPENFILE:
776 		return FS_FOpenFileByMode( VMA(1), VMA(2), args[3] );
777 
778 	case UI_FS_READ:
779 		FS_Read2( VMA(1), args[2], args[3] );
780 		return 0;
781 
782 	case UI_FS_WRITE:
783 		FS_Write( VMA(1), args[2], args[3] );
784 		return 0;
785 
786 	case UI_FS_FCLOSEFILE:
787 		FS_FCloseFile( args[1] );
788 		return 0;
789 
790 	case UI_FS_GETFILELIST:
791 		return FS_GetFileList( VMA(1), VMA(2), VMA(3), args[4] );
792 
793 	case UI_FS_SEEK:
794 		return FS_Seek( args[1], args[2], args[3] );
795 
796 	case UI_R_REGISTERMODEL:
797 		return re.RegisterModel( VMA(1) );
798 
799 	case UI_R_REGISTERSKIN:
800 		return re.RegisterSkin( VMA(1) );
801 
802 	case UI_R_REGISTERSHADERNOMIP:
803 		return re.RegisterShaderNoMip( VMA(1) );
804 
805 	case UI_R_CLEARSCENE:
806 		re.ClearScene();
807 		return 0;
808 
809 	case UI_R_ADDREFENTITYTOSCENE:
810 		re.AddRefEntityToScene( VMA(1) );
811 		return 0;
812 
813 	case UI_R_ADDPOLYTOSCENE:
814 		re.AddPolyToScene( args[1], args[2], VMA(3), 1 );
815 		return 0;
816 
817 	case UI_R_ADDLIGHTTOSCENE:
818 		re.AddLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) );
819 		return 0;
820 
821 	case UI_R_RENDERSCENE:
822 		re.RenderScene( VMA(1) );
823 		return 0;
824 
825 	case UI_R_SETCOLOR:
826 		re.SetColor( VMA(1) );
827 		return 0;
828 
829 	case UI_R_DRAWSTRETCHPIC:
830 		re.DrawStretchPic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9] );
831 		return 0;
832 
833   case UI_R_MODELBOUNDS:
834 		re.ModelBounds( args[1], VMA(2), VMA(3) );
835 		return 0;
836 
837 	case UI_UPDATESCREEN:
838 		SCR_UpdateScreen();
839 		return 0;
840 
841 	case UI_CM_LERPTAG:
842 		re.LerpTag( VMA(1), args[2], args[3], args[4], VMF(5), VMA(6) );
843 		return 0;
844 
845 	case UI_S_REGISTERSOUND:
846 		return S_RegisterSound( VMA(1), args[2] );
847 
848 	case UI_S_STARTLOCALSOUND:
849 		S_StartLocalSound( args[1], args[2] );
850 		return 0;
851 
852 	case UI_KEY_KEYNUMTOSTRINGBUF:
853 		Key_KeynumToStringBuf( args[1], VMA(2), args[3] );
854 		return 0;
855 
856 	case UI_KEY_GETBINDINGBUF:
857 		Key_GetBindingBuf( args[1], VMA(2), args[3] );
858 		return 0;
859 
860 	case UI_KEY_SETBINDING:
861 		Key_SetBinding( args[1], VMA(2) );
862 		return 0;
863 
864 	case UI_KEY_ISDOWN:
865 		return Key_IsDown( args[1] );
866 
867 	case UI_KEY_GETOVERSTRIKEMODE:
868 		return Key_GetOverstrikeMode();
869 
870 	case UI_KEY_SETOVERSTRIKEMODE:
871 		Key_SetOverstrikeMode( args[1] );
872 		return 0;
873 
874 	case UI_KEY_CLEARSTATES:
875 		Key_ClearStates();
876 		return 0;
877 
878 	case UI_KEY_GETCATCHER:
879 		return Key_GetCatcher();
880 
881 	case UI_KEY_SETCATCHER:
882 		// Don't allow the ui module to close the console
883 		Key_SetCatcher( args[1] | ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) );
884 		return 0;
885 
886 	case UI_GETCLIPBOARDDATA:
887 		CL_GetClipboardData( VMA(1), args[2] );
888 		return 0;
889 
890 	case UI_GETCLIENTSTATE:
891 		GetClientState( VMA(1) );
892 		return 0;
893 
894 	case UI_GETGLCONFIG:
895 		CL_GetGlconfig( VMA(1) );
896 		return 0;
897 
898 	case UI_GETCONFIGSTRING:
899 		return GetConfigString( args[1], VMA(2), args[3] );
900 
901 	case UI_LAN_LOADCACHEDSERVERS:
902 		LAN_LoadCachedServers();
903 		return 0;
904 
905 	case UI_LAN_SAVECACHEDSERVERS:
906 		LAN_SaveServersToCache();
907 		return 0;
908 
909 	case UI_LAN_ADDSERVER:
910 		return LAN_AddServer(args[1], VMA(2), VMA(3));
911 
912 	case UI_LAN_REMOVESERVER:
913 		LAN_RemoveServer(args[1], VMA(2));
914 		return 0;
915 
916 	case UI_LAN_GETPINGQUEUECOUNT:
917 		return LAN_GetPingQueueCount();
918 
919 	case UI_LAN_CLEARPING:
920 		LAN_ClearPing( args[1] );
921 		return 0;
922 
923 	case UI_LAN_GETPING:
924 		LAN_GetPing( args[1], VMA(2), args[3], VMA(4) );
925 		return 0;
926 
927 	case UI_LAN_GETPINGINFO:
928 		LAN_GetPingInfo( args[1], VMA(2), args[3] );
929 		return 0;
930 
931 	case UI_LAN_GETSERVERCOUNT:
932 		return LAN_GetServerCount(args[1]);
933 
934 	case UI_LAN_GETSERVERADDRESSSTRING:
935 		LAN_GetServerAddressString( args[1], args[2], VMA(3), args[4] );
936 		return 0;
937 
938 	case UI_LAN_GETSERVERINFO:
939 		LAN_GetServerInfo( args[1], args[2], VMA(3), args[4] );
940 		return 0;
941 
942 	case UI_LAN_GETSERVERPING:
943 		return LAN_GetServerPing( args[1], args[2] );
944 
945 	case UI_LAN_MARKSERVERVISIBLE:
946 		LAN_MarkServerVisible( args[1], args[2], args[3] );
947 		return 0;
948 
949 	case UI_LAN_SERVERISVISIBLE:
950 		return LAN_ServerIsVisible( args[1], args[2] );
951 
952 	case UI_LAN_UPDATEVISIBLEPINGS:
953 		return LAN_UpdateVisiblePings( args[1] );
954 
955 	case UI_LAN_RESETPINGS:
956 		LAN_ResetPings( args[1] );
957 		return 0;
958 
959 	case UI_LAN_SERVERSTATUS:
960 		return LAN_GetServerStatus( VMA(1), VMA(2), args[3] );
961 
962 	case UI_LAN_COMPARESERVERS:
963 		return LAN_CompareServers( args[1], args[2], args[3], args[4], args[5] );
964 
965 	case UI_MEMORY_REMAINING:
966 		return Hunk_MemoryRemaining();
967 
968 #ifndef STANDALONE
969 	case UI_GET_CDKEY:
970 		CLUI_GetCDKey( VMA(1), args[2] );
971 		return 0;
972 
973 	case UI_SET_CDKEY:
974 		CLUI_SetCDKey( VMA(1) );
975 		return 0;
976 #endif
977 
978 	case UI_SET_PBCLSTATUS:
979 		return 0;
980 
981 	case UI_R_REGISTERFONT:
982 		re.RegisterFont( VMA(1), args[2], VMA(3));
983 		return 0;
984 
985 	case UI_MEMSET:
986 		Com_Memset( VMA(1), args[2], args[3] );
987 		return 0;
988 
989 	case UI_MEMCPY:
990 		Com_Memcpy( VMA(1), VMA(2), args[3] );
991 		return 0;
992 
993 	case UI_STRNCPY:
994 		strncpy( VMA(1), VMA(2), args[3] );
995 		return args[1];
996 
997 	case UI_SIN:
998 		return FloatAsInt( sin( VMF(1) ) );
999 
1000 	case UI_COS:
1001 		return FloatAsInt( cos( VMF(1) ) );
1002 
1003 	case UI_ATAN2:
1004 		return FloatAsInt( atan2( VMF(1), VMF(2) ) );
1005 
1006 	case UI_SQRT:
1007 		return FloatAsInt( sqrt( VMF(1) ) );
1008 
1009 	case UI_FLOOR:
1010 		return FloatAsInt( floor( VMF(1) ) );
1011 
1012 	case UI_CEIL:
1013 		return FloatAsInt( ceil( VMF(1) ) );
1014 
1015 	case UI_PC_ADD_GLOBAL_DEFINE:
1016 		return botlib_export->PC_AddGlobalDefine( VMA(1) );
1017 	case UI_PC_LOAD_SOURCE:
1018 		return botlib_export->PC_LoadSourceHandle( VMA(1) );
1019 	case UI_PC_FREE_SOURCE:
1020 		return botlib_export->PC_FreeSourceHandle( args[1] );
1021 	case UI_PC_READ_TOKEN:
1022 		return botlib_export->PC_ReadTokenHandle( args[1], VMA(2) );
1023 	case UI_PC_SOURCE_FILE_AND_LINE:
1024 		return botlib_export->PC_SourceFileAndLine( args[1], VMA(2), VMA(3) );
1025 
1026 	case UI_S_STOPBACKGROUNDTRACK:
1027 		S_StopBackgroundTrack();
1028 		return 0;
1029 	case UI_S_STARTBACKGROUNDTRACK:
1030 		S_StartBackgroundTrack( VMA(1), VMA(2));
1031 		return 0;
1032 
1033 	case UI_REAL_TIME:
1034 		return Com_RealTime( VMA(1) );
1035 
1036 	case UI_CIN_PLAYCINEMATIC:
1037 	  Com_DPrintf("UI_CIN_PlayCinematic\n");
1038 	  return CIN_PlayCinematic(VMA(1), args[2], args[3], args[4], args[5], args[6]);
1039 
1040 	case UI_CIN_STOPCINEMATIC:
1041 	  return CIN_StopCinematic(args[1]);
1042 
1043 	case UI_CIN_RUNCINEMATIC:
1044 	  return CIN_RunCinematic(args[1]);
1045 
1046 	case UI_CIN_DRAWCINEMATIC:
1047 	  CIN_DrawCinematic(args[1]);
1048 	  return 0;
1049 
1050 	case UI_CIN_SETEXTENTS:
1051 	  CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]);
1052 	  return 0;
1053 
1054 	case UI_R_REMAP_SHADER:
1055 		re.RemapShader( VMA(1), VMA(2), VMA(3) );
1056 		return 0;
1057 
1058 #ifndef STANDALONE
1059 	case UI_VERIFY_CDKEY:
1060 		return CL_CDKeyValidate(VMA(1), VMA(2));
1061 #endif
1062 
1063 
1064 	default:
1065 		Com_Error( ERR_DROP, "Bad UI system trap: %ld", (long int) args[0] );
1066 
1067 	}
1068 
1069 	return 0;
1070 }
1071 
1072 /*
1073 ====================
1074 CL_ShutdownUI
1075 ====================
1076 */
CL_ShutdownUI(void)1077 void CL_ShutdownUI( void ) {
1078 	Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_UI );
1079 	cls.uiStarted = qfalse;
1080 	if ( !uivm ) {
1081 		return;
1082 	}
1083 	VM_Call( uivm, UI_SHUTDOWN );
1084 	VM_Free( uivm );
1085 	uivm = NULL;
1086 }
1087 
1088 /*
1089 ====================
1090 CL_InitUI
1091 ====================
1092 */
1093 #define UI_OLD_API_VERSION	4
1094 
CL_InitUI(void)1095 void CL_InitUI( void ) {
1096 	int		v;
1097 	vmInterpret_t		interpret;
1098 
1099 	// load the dll or bytecode
1100 	if ( cl_connectedToPureServer != 0 ) {
1101 		// if sv_pure is set we only allow qvms to be loaded
1102 		interpret = VMI_COMPILED;
1103 	}
1104 	else {
1105 		interpret = Cvar_VariableValue( "vm_ui" );
1106 	}
1107 	uivm = VM_Create( "ui", CL_UISystemCalls, interpret );
1108 	if ( !uivm ) {
1109 		Com_Error( ERR_FATAL, "VM_Create on UI failed" );
1110 	}
1111 
1112 	// sanity check
1113 	v = VM_Call( uivm, UI_GETAPIVERSION );
1114 	if (v == UI_OLD_API_VERSION) {
1115 //		Com_Printf(S_COLOR_YELLOW "WARNING: loading old Quake III Arena User Interface version %d\n", v );
1116 		// init for this gamestate
1117 		VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE));
1118 	}
1119 	else if (v != UI_API_VERSION) {
1120 		Com_Error( ERR_DROP, "User Interface is version %d, expected %d", v, UI_API_VERSION );
1121 		cls.uiStarted = qfalse;
1122 	}
1123 	else {
1124 		// init for this gamestate
1125 		VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE) );
1126 	}
1127 
1128 	// reset any CVAR_CHEAT cvars registered by ui
1129 	if ( !clc.demoplaying && !cl_connectedToCheatServer )
1130 		Cvar_SetCheatState();
1131 }
1132 
1133 #ifndef STANDALONE
UI_usesUniqueCDKey(void)1134 qboolean UI_usesUniqueCDKey( void ) {
1135 	if (uivm) {
1136 		return (VM_Call( uivm, UI_HASUNIQUECDKEY) == qtrue);
1137 	} else {
1138 		return qfalse;
1139 	}
1140 }
1141 #endif
1142 
1143 /*
1144 ====================
1145 UI_GameCommand
1146 
1147 See if the current console command is claimed by the ui
1148 ====================
1149 */
UI_GameCommand(void)1150 qboolean UI_GameCommand( void ) {
1151 	if ( !uivm ) {
1152 		return qfalse;
1153 	}
1154 
1155 	return VM_Call( uivm, UI_CONSOLE_COMMAND, cls.realtime );
1156 }
1157