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