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_AdrToStringwPort(server->adr));
300 		Info_SetValueForKey( info, "g_needpass", va("%i",server->g_needpass));
301 		Info_SetValueForKey( info, "g_humanplayers", va("%i",server->g_humanplayers));
302 		Q_strncpyz(buf, info, buflen);
303 	} else {
304 		if (buf) {
305 			buf[0] = '\0';
306 		}
307 	}
308 }
309 
310 /*
311 ====================
312 LAN_GetServerPing
313 ====================
314 */
LAN_GetServerPing(int source,int n)315 static int LAN_GetServerPing( int source, int n ) {
316 	serverInfo_t *server = NULL;
317 	switch (source) {
318 		case AS_LOCAL :
319 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
320 				server = &cls.localServers[n];
321 			}
322 			break;
323 		case AS_MPLAYER:
324 		case AS_GLOBAL :
325 			if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
326 				server = &cls.globalServers[n];
327 			}
328 			break;
329 		case AS_FAVORITES :
330 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
331 				server = &cls.favoriteServers[n];
332 			}
333 			break;
334 	}
335 	if (server) {
336 		return server->ping;
337 	}
338 	return -1;
339 }
340 
341 /*
342 ====================
343 LAN_GetServerPtr
344 ====================
345 */
LAN_GetServerPtr(int source,int n)346 static serverInfo_t *LAN_GetServerPtr( int source, int n ) {
347 	switch (source) {
348 		case AS_LOCAL :
349 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
350 				return &cls.localServers[n];
351 			}
352 			break;
353 		case AS_MPLAYER:
354 		case AS_GLOBAL :
355 			if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
356 				return &cls.globalServers[n];
357 			}
358 			break;
359 		case AS_FAVORITES :
360 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
361 				return &cls.favoriteServers[n];
362 			}
363 			break;
364 	}
365 	return NULL;
366 }
367 
368 /*
369 ====================
370 LAN_CompareServers
371 ====================
372 */
LAN_CompareServers(int source,int sortKey,int sortDir,int s1,int s2)373 static int LAN_CompareServers( int source, int sortKey, int sortDir, int s1, int s2 ) {
374 	int res;
375 	serverInfo_t *server1, *server2;
376 
377 	server1 = LAN_GetServerPtr(source, s1);
378 	server2 = LAN_GetServerPtr(source, s2);
379 	if (!server1 || !server2) {
380 		return 0;
381 	}
382 
383 	res = 0;
384 	switch( sortKey ) {
385 		case SORT_HOST:
386 			res = Q_stricmp( server1->hostName, server2->hostName );
387 			break;
388 
389 		case SORT_MAP:
390 			res = Q_stricmp( server1->mapName, server2->mapName );
391 			break;
392 		case SORT_CLIENTS:
393 			if (server1->clients < server2->clients) {
394 				res = -1;
395 			}
396 			else if (server1->clients > server2->clients) {
397 				res = 1;
398 			}
399 			else {
400 				res = 0;
401 			}
402 			break;
403 		case SORT_GAME:
404 			if (server1->gameType < server2->gameType) {
405 				res = -1;
406 			}
407 			else if (server1->gameType > server2->gameType) {
408 				res = 1;
409 			}
410 			else {
411 				res = 0;
412 			}
413 			break;
414 		case SORT_PING:
415 			if (server1->ping < server2->ping) {
416 				res = -1;
417 			}
418 			else if (server1->ping > server2->ping) {
419 				res = 1;
420 			}
421 			else {
422 				res = 0;
423 			}
424 			break;
425 	}
426 
427 	if (sortDir) {
428 		if (res < 0)
429 			return 1;
430 		if (res > 0)
431 			return -1;
432 		return 0;
433 	}
434 	return res;
435 }
436 
437 /*
438 ====================
439 LAN_GetPingQueueCount
440 ====================
441 */
LAN_GetPingQueueCount(void)442 static int LAN_GetPingQueueCount( void ) {
443 	return (CL_GetPingQueueCount());
444 }
445 
446 /*
447 ====================
448 LAN_ClearPing
449 ====================
450 */
LAN_ClearPing(int n)451 static void LAN_ClearPing( int n ) {
452 	CL_ClearPing( n );
453 }
454 
455 /*
456 ====================
457 LAN_GetPing
458 ====================
459 */
LAN_GetPing(int n,char * buf,int buflen,int * pingtime)460 static void LAN_GetPing( int n, char *buf, int buflen, int *pingtime ) {
461 	CL_GetPing( n, buf, buflen, pingtime );
462 }
463 
464 /*
465 ====================
466 LAN_GetPingInfo
467 ====================
468 */
LAN_GetPingInfo(int n,char * buf,int buflen)469 static void LAN_GetPingInfo( int n, char *buf, int buflen ) {
470 	CL_GetPingInfo( n, buf, buflen );
471 }
472 
473 /*
474 ====================
475 LAN_MarkServerVisible
476 ====================
477 */
LAN_MarkServerVisible(int source,int n,qboolean visible)478 static void LAN_MarkServerVisible(int source, int n, qboolean visible ) {
479 	if (n == -1) {
480 		int count = MAX_OTHER_SERVERS;
481 		serverInfo_t *server = NULL;
482 		switch (source) {
483 			case AS_LOCAL :
484 				server = &cls.localServers[0];
485 				break;
486 			case AS_MPLAYER:
487 			case AS_GLOBAL :
488 				server = &cls.globalServers[0];
489 				count = MAX_GLOBAL_SERVERS;
490 				break;
491 			case AS_FAVORITES :
492 				server = &cls.favoriteServers[0];
493 				break;
494 		}
495 		if (server) {
496 			for (n = 0; n < count; n++) {
497 				server[n].visible = visible;
498 			}
499 		}
500 
501 	} else {
502 		switch (source) {
503 			case AS_LOCAL :
504 				if (n >= 0 && n < MAX_OTHER_SERVERS) {
505 					cls.localServers[n].visible = visible;
506 				}
507 				break;
508 			case AS_MPLAYER:
509 			case AS_GLOBAL :
510 				if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
511 					cls.globalServers[n].visible = visible;
512 				}
513 				break;
514 			case AS_FAVORITES :
515 				if (n >= 0 && n < MAX_OTHER_SERVERS) {
516 					cls.favoriteServers[n].visible = visible;
517 				}
518 				break;
519 		}
520 	}
521 }
522 
523 
524 /*
525 =======================
526 LAN_ServerIsVisible
527 =======================
528 */
LAN_ServerIsVisible(int source,int n)529 static int LAN_ServerIsVisible(int source, int n ) {
530 	switch (source) {
531 		case AS_LOCAL :
532 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
533 				return cls.localServers[n].visible;
534 			}
535 			break;
536 		case AS_MPLAYER:
537 		case AS_GLOBAL :
538 			if (n >= 0 && n < MAX_GLOBAL_SERVERS) {
539 				return cls.globalServers[n].visible;
540 			}
541 			break;
542 		case AS_FAVORITES :
543 			if (n >= 0 && n < MAX_OTHER_SERVERS) {
544 				return cls.favoriteServers[n].visible;
545 			}
546 			break;
547 	}
548 	return qfalse;
549 }
550 
551 /*
552 =======================
553 LAN_UpdateVisiblePings
554 =======================
555 */
LAN_UpdateVisiblePings(int source)556 qboolean LAN_UpdateVisiblePings(int source ) {
557 	return CL_UpdateVisiblePings_f(source);
558 }
559 
560 /*
561 ====================
562 LAN_GetServerStatus
563 ====================
564 */
LAN_GetServerStatus(char * serverAddress,char * serverStatus,int maxLen)565 int LAN_GetServerStatus( char *serverAddress, char *serverStatus, int maxLen ) {
566 	return CL_ServerStatus( serverAddress, serverStatus, maxLen );
567 }
568 
569 /*
570 ====================
571 CL_GetGlConfig
572 ====================
573 */
CL_GetGlconfig(glconfig_t * config)574 static void CL_GetGlconfig( glconfig_t *config ) {
575 	*config = cls.glconfig;
576 }
577 
578 /*
579 ====================
580 CL_GetClipboardData
581 ====================
582 */
CL_GetClipboardData(char * buf,int buflen)583 static void CL_GetClipboardData( char *buf, int buflen ) {
584 	char	*cbd;
585 
586 	cbd = Sys_GetClipboardData();
587 
588 	if ( !cbd ) {
589 		*buf = 0;
590 		return;
591 	}
592 
593 	Q_strncpyz( buf, cbd, buflen );
594 
595 	Z_Free( cbd );
596 }
597 
598 /*
599 ====================
600 Key_KeynumToStringBuf
601 ====================
602 */
Key_KeynumToStringBuf(int keynum,char * buf,int buflen)603 static void Key_KeynumToStringBuf( int keynum, char *buf, int buflen ) {
604 	Q_strncpyz( buf, Key_KeynumToString( keynum ), buflen );
605 }
606 
607 /*
608 ====================
609 Key_GetBindingBuf
610 ====================
611 */
Key_GetBindingBuf(int keynum,char * buf,int buflen)612 static void Key_GetBindingBuf( int keynum, char *buf, int buflen ) {
613 	char	*value;
614 
615 	value = Key_GetBinding( keynum );
616 	if ( value ) {
617 		Q_strncpyz( buf, value, buflen );
618 	}
619 	else {
620 		*buf = 0;
621 	}
622 }
623 
624 /*
625 ====================
626 CLUI_GetCDKey
627 ====================
628 */
629 #ifndef STANDALONE
CLUI_GetCDKey(char * buf,int buflen)630 static void CLUI_GetCDKey( char *buf, int buflen ) {
631 	cvar_t	*fs;
632 	fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
633 	if (UI_usesUniqueCDKey() && fs && fs->string[0] != 0) {
634 		Com_Memcpy( buf, &cl_cdkey[16], 16);
635 		buf[16] = 0;
636 	} else {
637 		Com_Memcpy( buf, cl_cdkey, 16);
638 		buf[16] = 0;
639 	}
640 }
641 
642 
643 /*
644 ====================
645 CLUI_SetCDKey
646 ====================
647 */
CLUI_SetCDKey(char * buf)648 static void CLUI_SetCDKey( char *buf ) {
649 	cvar_t	*fs;
650 	fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
651 	if (UI_usesUniqueCDKey() && fs && fs->string[0] != 0) {
652 		Com_Memcpy( &cl_cdkey[16], buf, 16 );
653 		cl_cdkey[32] = 0;
654 		// set the flag so the fle will be written at the next opportunity
655 		cvar_modifiedFlags |= CVAR_ARCHIVE;
656 	} else {
657 		Com_Memcpy( cl_cdkey, buf, 16 );
658 		// set the flag so the fle will be written at the next opportunity
659 		cvar_modifiedFlags |= CVAR_ARCHIVE;
660 	}
661 }
662 #endif
663 
664 /*
665 ====================
666 GetConfigString
667 ====================
668 */
GetConfigString(int index,char * buf,int size)669 static int GetConfigString(int index, char *buf, int size)
670 {
671 	int		offset;
672 
673 	if (index < 0 || index >= MAX_CONFIGSTRINGS)
674 		return qfalse;
675 
676 	offset = cl.gameState.stringOffsets[index];
677 	if (!offset) {
678 		if( size ) {
679 			buf[0] = 0;
680 		}
681 		return qfalse;
682 	}
683 
684 	Q_strncpyz( buf, cl.gameState.stringData+offset, size);
685 
686 	return qtrue;
687 }
688 
689 /*
690 ====================
691 FloatAsInt
692 ====================
693 */
FloatAsInt(float f)694 static int FloatAsInt( float f ) {
695 	floatint_t fi;
696 	fi.f = f;
697 	return fi.i;
698 }
699 
700 /*
701 ====================
702 CL_UISystemCalls
703 
704 The ui module is making a system call
705 ====================
706 */
CL_UISystemCalls(intptr_t * args)707 intptr_t CL_UISystemCalls( intptr_t *args ) {
708 	switch( args[0] ) {
709 	case UI_ERROR:
710 		Com_Error( ERR_DROP, "%s", (const char*)VMA(1) );
711 		return 0;
712 
713 	case UI_PRINT:
714 		Com_Printf( "%s", (const char*)VMA(1) );
715 		return 0;
716 
717 	case UI_MILLISECONDS:
718 		return Sys_Milliseconds();
719 
720 	case UI_CVAR_REGISTER:
721 		Cvar_Register( VMA(1), VMA(2), VMA(3), args[4] );
722 		return 0;
723 
724 	case UI_CVAR_UPDATE:
725 		Cvar_Update( VMA(1) );
726 		return 0;
727 
728 	case UI_CVAR_SET:
729 		Cvar_Set( VMA(1), VMA(2) );
730 		return 0;
731 
732 	case UI_CVAR_VARIABLEVALUE:
733 		return FloatAsInt( Cvar_VariableValue( VMA(1) ) );
734 
735 	case UI_CVAR_VARIABLESTRINGBUFFER:
736 		Cvar_VariableStringBuffer( VMA(1), VMA(2), args[3] );
737 		return 0;
738 
739 	case UI_CVAR_SETVALUE:
740 		Cvar_SetValue( VMA(1), VMF(2) );
741 		return 0;
742 
743 	case UI_CVAR_RESET:
744 		Cvar_Reset( VMA(1) );
745 		return 0;
746 
747 	case UI_CVAR_CREATE:
748 		Cvar_Get( VMA(1), VMA(2), args[3] );
749 		return 0;
750 
751 	case UI_CVAR_INFOSTRINGBUFFER:
752 		Cvar_InfoStringBuffer( args[1], VMA(2), args[3] );
753 		return 0;
754 
755 	case UI_ARGC:
756 		return Cmd_Argc();
757 
758 	case UI_ARGV:
759 		Cmd_ArgvBuffer( args[1], VMA(2), args[3] );
760 		return 0;
761 
762 	case UI_CMD_EXECUTETEXT:
763 		if(args[1] == 0
764 		&& (!strncmp(VMA(2), "snd_restart", 11)
765 		|| !strncmp(VMA(2), "vid_restart", 11)
766 		|| !strncmp(VMA(2), "quit", 5)))
767 		{
768 			Com_Printf (S_COLOR_YELLOW "turning EXEC_NOW '%.11s' into EXEC_INSERT\n", (const char*)VMA(2));
769 			args[1] = EXEC_INSERT;
770 		}
771 		Cbuf_ExecuteText( args[1], VMA(2) );
772 		return 0;
773 
774 	case UI_FS_FOPENFILE:
775 		return FS_FOpenFileByMode( VMA(1), VMA(2), args[3] );
776 
777 	case UI_FS_READ:
778 		FS_Read2( VMA(1), args[2], args[3] );
779 		return 0;
780 
781 	case UI_FS_WRITE:
782 		FS_Write( VMA(1), args[2], args[3] );
783 		return 0;
784 
785 	case UI_FS_FCLOSEFILE:
786 		FS_FCloseFile( args[1] );
787 		return 0;
788 
789 	case UI_FS_GETFILELIST:
790 		return FS_GetFileList( VMA(1), VMA(2), VMA(3), args[4] );
791 
792 	case UI_FS_SEEK:
793 		return FS_Seek( args[1], args[2], args[3] );
794 
795 	case UI_R_REGISTERMODEL:
796 		return re.RegisterModel( VMA(1) );
797 
798 	case UI_R_REGISTERSKIN:
799 		return re.RegisterSkin( VMA(1) );
800 
801 	case UI_R_REGISTERSHADERNOMIP:
802 		return re.RegisterShaderNoMip( VMA(1) );
803 
804 	case UI_R_CLEARSCENE:
805 		re.ClearScene();
806 		return 0;
807 
808 	case UI_R_ADDREFENTITYTOSCENE:
809 		re.AddRefEntityToScene( VMA(1) );
810 		return 0;
811 
812 	case UI_R_ADDPOLYTOSCENE:
813 		re.AddPolyToScene( args[1], args[2], VMA(3), 1 );
814 		return 0;
815 
816 	case UI_R_ADDLIGHTTOSCENE:
817 		re.AddLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) );
818 		return 0;
819 
820 	case UI_R_RENDERSCENE:
821 		re.RenderScene( VMA(1) );
822 		return 0;
823 
824 	case UI_R_SETCOLOR:
825 		re.SetColor( VMA(1) );
826 		return 0;
827 
828 	case UI_R_DRAWSTRETCHPIC:
829 		re.DrawStretchPic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9] );
830 		return 0;
831 
832   case UI_R_MODELBOUNDS:
833 		re.ModelBounds( args[1], VMA(2), VMA(3) );
834 		return 0;
835 
836 	case UI_UPDATESCREEN:
837 		SCR_UpdateScreen();
838 		return 0;
839 
840 	case UI_CM_LERPTAG:
841 		re.LerpTag( VMA(1), args[2], args[3], args[4], VMF(5), VMA(6) );
842 		return 0;
843 
844 	case UI_S_REGISTERSOUND:
845 		return S_RegisterSound( VMA(1), args[2] );
846 
847 	case UI_S_STARTLOCALSOUND:
848 		S_StartLocalSound( args[1], args[2] );
849 		return 0;
850 
851 	case UI_KEY_KEYNUMTOSTRINGBUF:
852 		Key_KeynumToStringBuf( args[1], VMA(2), args[3] );
853 		return 0;
854 
855 	case UI_KEY_GETBINDINGBUF:
856 		Key_GetBindingBuf( args[1], VMA(2), args[3] );
857 		return 0;
858 
859 	case UI_KEY_SETBINDING:
860 		Key_SetBinding( args[1], VMA(2) );
861 		return 0;
862 
863 	case UI_KEY_ISDOWN:
864 		return Key_IsDown( args[1] );
865 
866 	case UI_KEY_GETOVERSTRIKEMODE:
867 		return Key_GetOverstrikeMode();
868 
869 	case UI_KEY_SETOVERSTRIKEMODE:
870 		Key_SetOverstrikeMode( args[1] );
871 		return 0;
872 
873 	case UI_KEY_CLEARSTATES:
874 		Key_ClearStates();
875 		return 0;
876 
877 	case UI_KEY_GETCATCHER:
878 		return Key_GetCatcher();
879 
880 	case UI_KEY_SETCATCHER:
881 		// Don't allow the ui module to close the console
882 		Key_SetCatcher( args[1] | ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) );
883 		return 0;
884 
885 	case UI_GETCLIPBOARDDATA:
886 		CL_GetClipboardData( VMA(1), args[2] );
887 		return 0;
888 
889 	case UI_GETCLIENTSTATE:
890 		GetClientState( VMA(1) );
891 		return 0;
892 
893 	case UI_GETGLCONFIG:
894 		CL_GetGlconfig( VMA(1) );
895 		return 0;
896 
897 	case UI_GETCONFIGSTRING:
898 		return GetConfigString( args[1], VMA(2), args[3] );
899 
900 	case UI_LAN_LOADCACHEDSERVERS:
901 		LAN_LoadCachedServers();
902 		return 0;
903 
904 	case UI_LAN_SAVECACHEDSERVERS:
905 		LAN_SaveServersToCache();
906 		return 0;
907 
908 	case UI_LAN_ADDSERVER:
909 		return LAN_AddServer(args[1], VMA(2), VMA(3));
910 
911 	case UI_LAN_REMOVESERVER:
912 		LAN_RemoveServer(args[1], VMA(2));
913 		return 0;
914 
915 	case UI_LAN_GETPINGQUEUECOUNT:
916 		return LAN_GetPingQueueCount();
917 
918 	case UI_LAN_CLEARPING:
919 		LAN_ClearPing( args[1] );
920 		return 0;
921 
922 	case UI_LAN_GETPING:
923 		LAN_GetPing( args[1], VMA(2), args[3], VMA(4) );
924 		return 0;
925 
926 	case UI_LAN_GETPINGINFO:
927 		LAN_GetPingInfo( args[1], VMA(2), args[3] );
928 		return 0;
929 
930 	case UI_LAN_GETSERVERCOUNT:
931 		return LAN_GetServerCount(args[1]);
932 
933 	case UI_LAN_GETSERVERADDRESSSTRING:
934 		LAN_GetServerAddressString( args[1], args[2], VMA(3), args[4] );
935 		return 0;
936 
937 	case UI_LAN_GETSERVERINFO:
938 		LAN_GetServerInfo( args[1], args[2], VMA(3), args[4] );
939 		return 0;
940 
941 	case UI_LAN_GETSERVERPING:
942 		return LAN_GetServerPing( args[1], args[2] );
943 
944 	case UI_LAN_MARKSERVERVISIBLE:
945 		LAN_MarkServerVisible( args[1], args[2], args[3] );
946 		return 0;
947 
948 	case UI_LAN_SERVERISVISIBLE:
949 		return LAN_ServerIsVisible( args[1], args[2] );
950 
951 	case UI_LAN_UPDATEVISIBLEPINGS:
952 		return LAN_UpdateVisiblePings( args[1] );
953 
954 	case UI_LAN_RESETPINGS:
955 		LAN_ResetPings( args[1] );
956 		return 0;
957 
958 	case UI_LAN_SERVERSTATUS:
959 		return LAN_GetServerStatus( VMA(1), VMA(2), args[3] );
960 
961 	case UI_LAN_COMPARESERVERS:
962 		return LAN_CompareServers( args[1], args[2], args[3], args[4], args[5] );
963 
964 	case UI_MEMORY_REMAINING:
965 		return Hunk_MemoryRemaining();
966 
967 #ifndef STANDABONE
968 	case UI_GET_CDKEY:
969 		return 0;
970 
971 	case UI_SET_CDKEY:
972 		return 0;
973 #endif
974 
975 	case UI_SET_PBCLSTATUS:
976 		return 0;
977 
978 	case UI_R_REGISTERFONT:
979 		re.RegisterFont( VMA(1), args[2], VMA(3));
980 		return 0;
981 
982 	case UI_MEMSET:
983 		Com_Memset( VMA(1), args[2], args[3] );
984 		return 0;
985 
986 	case UI_MEMCPY:
987 		Com_Memcpy( VMA(1), VMA(2), args[3] );
988 		return 0;
989 
990 	case UI_STRNCPY:
991 		strncpy( VMA(1), VMA(2), args[3] );
992 		return args[1];
993 
994 	case UI_SIN:
995 		return FloatAsInt( sin( VMF(1) ) );
996 
997 	case UI_COS:
998 		return FloatAsInt( cos( VMF(1) ) );
999 
1000 	case UI_ATAN2:
1001 		return FloatAsInt( atan2( VMF(1), VMF(2) ) );
1002 
1003 	case UI_SQRT:
1004 		return FloatAsInt( sqrt( VMF(1) ) );
1005 
1006 	case UI_FLOOR:
1007 		return FloatAsInt( floor( VMF(1) ) );
1008 
1009 	case UI_CEIL:
1010 		return FloatAsInt( ceil( VMF(1) ) );
1011 
1012 	case UI_PC_ADD_GLOBAL_DEFINE:
1013 		return botlib_export->PC_AddGlobalDefine( VMA(1) );
1014 	case UI_PC_LOAD_SOURCE:
1015 		return botlib_export->PC_LoadSourceHandle( VMA(1) );
1016 	case UI_PC_FREE_SOURCE:
1017 		return botlib_export->PC_FreeSourceHandle( args[1] );
1018 	case UI_PC_READ_TOKEN:
1019 		return botlib_export->PC_ReadTokenHandle( args[1], VMA(2) );
1020 	case UI_PC_SOURCE_FILE_AND_LINE:
1021 		return botlib_export->PC_SourceFileAndLine( args[1], VMA(2), VMA(3) );
1022 
1023 	case UI_S_STOPBACKGROUNDTRACK:
1024 		S_StopBackgroundTrack();
1025 		return 0;
1026 	case UI_S_STARTBACKGROUNDTRACK:
1027 		S_StartBackgroundTrack( VMA(1), VMA(2));
1028 		return 0;
1029 
1030 	case UI_REAL_TIME:
1031 		return Com_RealTime( VMA(1) );
1032 
1033 	case UI_CIN_PLAYCINEMATIC:
1034 	  Com_DPrintf("UI_CIN_PlayCinematic\n");
1035 	  return CIN_PlayCinematic(VMA(1), args[2], args[3], args[4], args[5], args[6]);
1036 
1037 	case UI_CIN_STOPCINEMATIC:
1038 	  return CIN_StopCinematic(args[1]);
1039 
1040 	case UI_CIN_RUNCINEMATIC:
1041 	  return CIN_RunCinematic(args[1]);
1042 
1043 	case UI_CIN_DRAWCINEMATIC:
1044 	  CIN_DrawCinematic(args[1]);
1045 	  return 0;
1046 
1047 	case UI_CIN_SETEXTENTS:
1048 	  CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]);
1049 	  return 0;
1050 
1051 	case UI_R_REMAP_SHADER:
1052 		re.RemapShader( VMA(1), VMA(2), VMA(3) );
1053 		return 0;
1054 
1055 	case UI_VERIFY_CDKEY:
1056 		return 1;
1057 
1058 
1059 	default:
1060 		Com_Error( ERR_DROP, "Bad UI system trap: %ld", (long int) args[0] );
1061 
1062 	}
1063 
1064 	return 0;
1065 }
1066 
1067 /*
1068 ====================
1069 CL_ShutdownUI
1070 ====================
1071 */
CL_ShutdownUI(void)1072 void CL_ShutdownUI( void ) {
1073 	Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_UI );
1074 	cls.uiStarted = qfalse;
1075 	if ( !uivm ) {
1076 		return;
1077 	}
1078 	VM_Call( uivm, UI_SHUTDOWN );
1079 	VM_Free( uivm );
1080 	uivm = NULL;
1081 }
1082 
1083 /*
1084 ====================
1085 CL_InitUI
1086 ====================
1087 */
1088 #define UI_OLD_API_VERSION	4
1089 
CL_InitUI(void)1090 void CL_InitUI( void ) {
1091 	int		v;
1092 	vmInterpret_t		interpret;
1093 
1094 	// load the dll or bytecode
1095 	if ( cl_connectedToPureServer != 0 ) {
1096 		// if sv_pure is set we only allow qvms to be loaded
1097 		interpret = VMI_COMPILED;
1098 	}
1099 	else {
1100 		interpret = Cvar_VariableValue( "vm_ui" );
1101 	}
1102 	uivm = VM_Create( "ui", CL_UISystemCalls, interpret );
1103 	if ( !uivm ) {
1104 		Com_Error( ERR_FATAL, "VM_Create on UI failed" );
1105 	}
1106 
1107 	// sanity check
1108 	v = VM_Call( uivm, UI_GETAPIVERSION );
1109 	if (v == UI_OLD_API_VERSION) {
1110 //		Com_Printf(S_COLOR_YELLOW "WARNING: loading old Quake III Arena User Interface version %d\n", v );
1111 		// init for this gamestate
1112 		VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE));
1113 	}
1114 	else if (v != UI_API_VERSION) {
1115 		Com_Error( ERR_DROP, "User Interface is version %d, expected %d", v, UI_API_VERSION );
1116 		cls.uiStarted = qfalse;
1117 	}
1118 	else {
1119 		// init for this gamestate
1120 		VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE) );
1121 	}
1122 
1123 	// reset any CVAR_CHEAT cvars registered by ui
1124 	if ( !clc.demoplaying && !cl_connectedToCheatServer )
1125 		Cvar_SetCheatState();
1126 }
1127 
1128 #ifndef STANDABONE
UI_usesUniqueCDKey(void)1129 qboolean UI_usesUniqueCDKey( void ) {
1130 
1131 		return qfalse;
1132 }
1133 #endif
1134 
1135 /*
1136 ====================
1137 UI_GameCommand
1138 
1139 See if the current console command is claimed by the ui
1140 ====================
1141 */
UI_GameCommand(void)1142 qboolean UI_GameCommand( void ) {
1143 	if ( !uivm ) {
1144 		return qfalse;
1145 	}
1146 
1147 	return VM_Call( uivm, UI_CONSOLE_COMMAND, cls.realtime );
1148 }
1149