migrated cls.message and client->message buffers into netconn_t struct
[xonotic/darkplaces.git] / mvm_cmds.c
1 #include "prvm_cmds.h"
2
3 //============================================================================
4 // Menu
5
6 char *vm_m_extensions =
7 "DP_CINEMATIC_DPV";
8
9 /*
10 =========
11 VM_M_precache_file
12
13 string  precache_file(string)
14 =========
15 */
16 void VM_M_precache_file (void)
17 {       // precache_file is only used to copy files with qcc, it does nothing
18         VM_SAFEPARMCOUNT(1,VM_precache_file);
19
20         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
21 }
22
23 /*
24 =========
25 VM_M_preache_error
26
27 used instead of the other VM_precache_* functions in the builtin list
28 =========
29 */
30
31 void VM_M_precache_error (void)
32 {
33         PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
34 }
35
36 /*
37 =========
38 VM_M_precache_sound
39
40 string  precache_sound (string sample)
41 =========
42 */
43 void VM_M_precache_sound (void)
44 {
45         const char      *s;
46
47         VM_SAFEPARMCOUNT(1, VM_precache_sound);
48
49         s = PRVM_G_STRING(OFS_PARM0);
50         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
51         VM_CheckEmptyString (s);
52
53         if(snd_initialized.integer && !S_PrecacheSound (s,true, true))
54                 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
55 }
56
57 /*
58 =========
59 VM_M_setmousetarget
60
61 setmousetarget(float target)
62 =========
63 */
64 void VM_M_setmousetarget(void)
65 {
66         VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
67
68         switch((int)PRVM_G_FLOAT(OFS_PARM0))
69         {
70         case 1:
71                 in_client_mouse = false;
72                 break;
73         case 2:
74                 in_client_mouse = true;
75                 break;
76         default:
77                 PRVM_ERROR("VM_M_setmousetarget: wrong destination %f !",PRVM_G_FLOAT(OFS_PARM0));
78         }
79 }
80
81 /*
82 =========
83 VM_M_getmousetarget
84
85 float   getmousetarget
86 =========
87 */
88 void VM_M_getmousetarget(void)
89 {
90         VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
91
92         if(in_client_mouse)
93                 PRVM_G_FLOAT(OFS_RETURN) = 2;
94         else
95                 PRVM_G_FLOAT(OFS_RETURN) = 1;
96 }
97
98
99
100 /*
101 =========
102 VM_M_setkeydest
103
104 setkeydest(float dest)
105 =========
106 */
107 void VM_M_setkeydest(void)
108 {
109         VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
110
111         switch((int)PRVM_G_FLOAT(OFS_PARM0))
112         {
113         case 0:
114                 // key_game
115                 key_dest = key_game;
116                 break;
117         case 2:
118                 // key_menu
119                 key_dest = key_menu;
120                 break;
121         case 1:
122                 // key_message
123                 // key_dest = key_message
124                 // break;
125         default:
126                 PRVM_ERROR("VM_M_setkeydest: wrong destination %f !", PRVM_G_FLOAT(OFS_PARM0));
127         }
128 }
129
130 /*
131 =========
132 VM_M_getkeydest
133
134 float   getkeydest
135 =========
136 */
137 void VM_M_getkeydest(void)
138 {
139         VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
140
141         // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
142         switch(key_dest)
143         {
144         case key_game:
145                 PRVM_G_FLOAT(OFS_RETURN) = 0;
146                 break;
147         case key_menu:
148                 PRVM_G_FLOAT(OFS_RETURN) = 2;
149                 break;
150         case key_message:
151                 // not supported
152                 // PRVM_G_FLOAT(OFS_RETURN) = 1;
153                 // break;
154         default:
155                 PRVM_G_FLOAT(OFS_RETURN) = 3;
156         }
157 }
158
159 /*
160 =========
161 VM_M_callfunction
162
163         callfunction(...,string function_name)
164 Extension: pass
165 =========
166 */
167 mfunction_t *PRVM_ED_FindFunction (const char *name);
168 void VM_M_callfunction(void)
169 {
170         mfunction_t *func;
171         const char *s;
172
173         if(prog->argc == 0)
174                 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !");
175
176         s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
177
178         if(!s)
179                 PRVM_ERROR("VM_M_callfunction: null string !");
180
181         VM_CheckEmptyString(s);
182
183         func = PRVM_ED_FindFunction(s);
184
185         if(!func)
186                 PRVM_ERROR("VM_M_callfunciton: function %s not found !", s);
187         else if (func->first_statement < 0)
188         {
189                 // negative statements are built in functions
190                 int builtinnumber = -func->first_statement;
191                 prog->xfunction->builtinsprofile++;
192                 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
193                         prog->builtins[builtinnumber]();
194                 else
195                         PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
196         }
197         else if(func > 0)
198         {
199                 prog->argc--;
200                 PRVM_ExecuteProgram(func - prog->functions,"");
201                 prog->argc++;
202         }
203 }
204
205 /*
206 =========
207 VM_M_isfunction
208
209 float   isfunction(string function_name)
210 =========
211 */
212 mfunction_t *PRVM_ED_FindFunction (const char *name);
213 void VM_M_isfunction(void)
214 {
215         mfunction_t *func;
216         const char *s;
217
218         VM_SAFEPARMCOUNT(1, VM_M_isfunction);
219
220         s = PRVM_G_STRING(OFS_PARM0);
221
222         if(!s)
223                 PRVM_ERROR("VM_M_isfunction: null string !");
224
225         VM_CheckEmptyString(s);
226
227         func = PRVM_ED_FindFunction(s);
228
229         if(!func)
230                 PRVM_G_FLOAT(OFS_RETURN) = false;
231         else
232                 PRVM_G_FLOAT(OFS_RETURN) = true;
233 }
234
235 /*
236 =========
237 VM_M_writetofile
238
239         writetofile(float fhandle, entity ent)
240 =========
241 */
242 void VM_M_writetofile(void)
243 {
244         prvm_edict_t * ent;
245         qfile_t *file;
246
247         VM_SAFEPARMCOUNT(2, VM_M_writetofile);
248
249         file = VM_GetFileHandle( PRVM_G_FLOAT(OFS_PARM0) );
250         if( !file ) {
251                 return;
252         }
253
254         ent = PRVM_G_EDICT(OFS_PARM1);
255         if(ent->priv.required->free)
256         {
257                 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
258                 return;
259         }
260
261         PRVM_ED_Write (file, ent);
262 }
263
264 /*
265 =========
266 VM_M_getresolution
267
268 vector  getresolution(float number)
269 =========
270 */
271 extern unsigned short video_resolutions[][2];
272 void VM_M_getresolution(void)
273 {
274         int nr;
275         VM_SAFEPARMCOUNT(1, VM_getresolution);
276
277         nr = PRVM_G_FLOAT(OFS_PARM0);
278
279
280         PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
281         PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
282         PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
283 }
284
285 /*
286 =========
287 VM_M_findkeysforcommand
288
289 string  findkeysforcommand(string command)
290
291 the returned string is an altstring
292 =========
293 */
294 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
295
296 void M_FindKeysForCommand(const char *command, int *keys);
297 void VM_M_findkeysforcommand(void)
298 {
299         const char *cmd;
300         char *ret;
301         int keys[NUMKEYS];
302         int i;
303
304         VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
305
306         cmd = PRVM_G_STRING(OFS_PARM0);
307
308         VM_CheckEmptyString(cmd);
309
310         (ret = VM_GetTempString())[0] = 0;
311
312         M_FindKeysForCommand(cmd, keys);
313
314         for(i = 0; i < NUMKEYS; i++)
315                 ret = strcat(ret, va(" \'%i\'", keys[i]));
316
317         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(ret);
318 }
319
320 /*
321 =========
322 VM_M_getserverliststat
323
324 float   getserverliststat(float type)
325 =========
326 */
327 /*
328         type:
329 0       serverlist_viewcount
330 1   serverlist_totalcount
331 2       masterquerycount
332 3       masterreplycount
333 4       serverquerycount
334 5       serverreplycount
335 6       sortfield
336 7       sortdescending
337 */
338 void VM_M_getserverliststat( void )
339 {
340         int type;
341         VM_SAFEPARMCOUNT ( 1, VM_M_getserverliststat );
342
343         PRVM_G_FLOAT( OFS_RETURN ) = 0;
344
345         type = PRVM_G_FLOAT( OFS_PARM0 );
346         switch(type)
347         {
348         case 0:
349                 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_viewcount;
350                 return;
351         case 1:
352                 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_cachecount;
353         case 2:
354                 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
355                 return;
356         case 3:
357                 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
358                 return;
359         case 4:
360                 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
361                 return;
362         case 5:
363                 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
364                 return;
365         case 6:
366                 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortbyfield;
367                 return;
368         case 7:
369                 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortdescending;
370                 return;
371         default:
372                 Con_Printf( "VM_M_getserverliststat: bad type %i!\n", type );
373         }
374 }
375
376 /*
377 ========================
378 VM_M_resetserverlistmasks
379
380 resetserverlistmasks()
381 ========================
382 */
383 void VM_M_resetserverlistmasks( void )
384 {
385         ServerList_ResetMasks();
386 }
387
388
389 /*
390 ========================
391 VM_M_setserverlistmaskstring
392
393 setserverlistmaskstring(float mask, float fld, string str, float op)
394 0-511           and
395 512 - 1024      or
396 ========================
397 */
398 void VM_M_setserverlistmaskstring( void )
399 {
400         const char *str;
401         int masknr;
402         serverlist_mask_t *mask;
403         int field;
404
405         VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmaskstring );
406         str = PRVM_G_STRING( OFS_PARM2 );
407         if( !str )
408                 PRVM_ERROR( "VM_M_setserverlistmaskstring: null string passed!" );
409
410         masknr = PRVM_G_FLOAT( OFS_PARM0 );
411         if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
412                 mask = &serverlist_andmasks[masknr];
413         else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
414                 mask = &serverlist_ormasks[masknr - 512 ];
415         else {
416                 Con_Printf( "VM_M_setserverlistmaskstring: invalid mask number %i\n", masknr );
417                 return;
418         }
419
420         field = (int) PRVM_G_FLOAT( OFS_PARM1 );
421
422         switch( field ) {
423                 case SLIF_CNAME:
424                         strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
425                         break;
426                 case SLIF_NAME:
427                         strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name)  );
428                         break;
429                 case SLIF_MAP:
430                         strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map)  );
431                         break;
432                 case SLIF_MOD:
433                         strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod)  );
434                         break;
435                 case SLIF_GAME:
436                         strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game)  );
437                         break;
438                 default:
439                         Con_Printf( "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
440                         return;
441         }
442
443         mask->active = true;
444         mask->tests[field] = (serverlist_maskop_t)((int)PRVM_G_FLOAT( OFS_PARM3 ));
445 }
446
447 /*
448 ========================
449 VM_M_setserverlistmasknumber
450
451 setserverlistmasknumber(float mask, float fld, float num, float op)
452
453 0-511           and
454 512 - 1024      or
455 ========================
456 */
457 void VM_M_setserverlistmasknumber( void )
458 {
459         int number;
460         serverlist_mask_t *mask;
461         int     masknr;
462         int field;
463         VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmasknumber );
464
465         masknr = PRVM_G_FLOAT( OFS_PARM0 );
466         if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
467                 mask = &serverlist_andmasks[masknr];
468         else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
469                 mask = &serverlist_ormasks[masknr - 512 ];
470         else {
471                 Con_Printf( "VM_M_setserverlistmasknumber: invalid mask number %i\n", masknr );
472                 return;
473         }
474
475         number = PRVM_G_FLOAT( OFS_PARM2 );
476         field = (int) PRVM_G_FLOAT( OFS_PARM1 );
477
478         switch( field ) {
479                 case SLIF_MAXPLAYERS:
480                         mask->info.maxplayers = number;
481                         break;
482                 case SLIF_NUMPLAYERS:
483                         mask->info.numplayers = number;
484                         break;
485                 case SLIF_PING:
486                         mask->info.ping = number;
487                         break;
488                 case SLIF_PROTOCOL:
489                         mask->info.protocol = number;
490                         break;
491                 default:
492                         Con_Printf( "VM_M_setserverlistmasknumber: Bad field number %i passed!\n", field );
493                         return;
494         }
495
496         mask->active = true;
497         mask->tests[field] = (serverlist_maskop_t)((int)PRVM_G_FLOAT( OFS_PARM3 ));
498 }
499
500
501 /*
502 ========================
503 VM_M_resortserverlist
504
505 resortserverlist
506 ========================
507 */
508 void VM_M_resortserverlist( void )
509 {
510         ServerList_RebuildViewList();
511 }
512
513 /*
514 =========
515 VM_M_getserverliststring
516
517 string  getserverliststring(float field, float hostnr)
518 =========
519 */
520 void VM_M_getserverliststring(void)
521 {
522         serverlist_entry_t *cache;
523         int hostnr;
524
525         VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
526
527         PRVM_G_INT(OFS_RETURN) = 0;
528
529         hostnr = PRVM_G_FLOAT(OFS_PARM1);
530
531         if(hostnr < 0 || hostnr >= serverlist_viewcount)
532         {
533                 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
534                 return;
535         }
536         cache = serverlist_viewlist[hostnr];
537         switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
538                 case SLIF_CNAME:
539                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.cname );
540                         break;
541                 case SLIF_NAME:
542                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.name );
543                         break;
544                 case SLIF_GAME:
545                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.game );
546                         break;
547                 case SLIF_MOD:
548                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.mod );
549                         break;
550                 case SLIF_MAP:
551                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.map );
552                         break;
553                 // TODO remove this again
554                 case 1024:
555                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line1 );
556                         break;
557                 case 1025:
558                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line2 );
559                         break;
560                 default:
561                         Con_Print("VM_M_getserverliststring: bad field number passed!\n");
562         }
563 }
564
565 /*
566 =========
567 VM_M_getserverlistnumber
568
569 float   getserverlistnumber(float field, float hostnr)
570 =========
571 */
572 void VM_M_getserverlistnumber(void)
573 {
574         serverlist_entry_t *cache;
575         int hostnr;
576
577         VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
578
579         PRVM_G_INT(OFS_RETURN) = 0;
580
581         hostnr = PRVM_G_FLOAT(OFS_PARM1);
582
583         if(hostnr < 0 || hostnr >= serverlist_viewcount)
584         {
585                 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
586                 return;
587         }
588         cache = serverlist_viewlist[hostnr];
589         switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
590                 case SLIF_MAXPLAYERS:
591                         PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
592                         break;
593                 case SLIF_NUMPLAYERS:
594                         PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
595                         break;
596                 case SLIF_PING:
597                         PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
598                         break;
599                 case SLIF_PROTOCOL:
600                         PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
601                         break;
602                 default:
603                         Con_Print("VM_M_getserverlistnumber: bad field number passed!\n");
604         }
605 }
606
607 /*
608 ========================
609 VM_M_setserverlistsort
610
611 setserverlistsort(float field, float descending)
612 ========================
613 */
614 void VM_M_setserverlistsort( void )
615 {
616         VM_SAFEPARMCOUNT( 2, VM_M_setserverlistsort );
617
618         serverlist_sortbyfield = (serverlist_infofield_t)((int)PRVM_G_FLOAT( OFS_PARM0 ));
619         serverlist_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
620 }
621
622 /*
623 ========================
624 VM_M_refreshserverlist
625
626 refreshserverlist()
627 ========================
628 */
629 void VM_M_refreshserverlist( void )
630 {
631         VM_SAFEPARMCOUNT( 0, VM_M_refreshserverlist );
632         ServerList_QueryList();
633 }
634
635 /*
636 ========================
637 VM_M_getserverlistindexforkey
638
639 float getserverlistindexforkey(string key)
640 ========================
641 */
642 void VM_M_getserverlistindexforkey( void )
643 {
644         const char *key;
645         VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
646
647         key = PRVM_G_STRING( OFS_PARM0 );
648         VM_CheckEmptyString( key );
649
650         if( !strcmp( key, "cname" ) )
651                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_CNAME;
652         else if( !strcmp( key, "ping" ) )
653                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PING;
654         else if( !strcmp( key, "game" ) )
655                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_GAME;
656         else if( !strcmp( key, "mod" ) )
657                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MOD;
658         else if( !strcmp( key, "map" ) )
659                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAP;
660         else if( !strcmp( key, "name" ) )
661                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NAME;
662         else if( !strcmp( key, "maxplayers" ) )
663                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAXPLAYERS;
664         else if( !strcmp( key, "numplayers" ) )
665                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NUMPLAYERS;
666         else if( !strcmp( key, "protocol" ) )
667                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PROTOCOL;
668         else
669                 PRVM_G_FLOAT( OFS_RETURN ) = -1;
670 }
671
672 /*
673 ========================
674 VM_M_addwantedserverlistkey
675
676 addwantedserverlistkey(string key)
677 ========================
678 */
679 void VM_M_addwantedserverlistkey( void )
680 {
681         VM_SAFEPARMCOUNT( 1, VM_M_addwantedserverlistkey );
682 }
683
684 /*
685 ===============================================================================
686 MESSAGE WRITING
687
688 used only for client and menu
689 severs uses VM_SV_...
690
691 Write*(* data, float type, float to)
692
693 ===============================================================================
694 */
695
696 #define MSG_BROADCAST   0               // unreliable to all
697 #define MSG_ONE                 1               // reliable to one (msg_entity)
698 #define MSG_ALL                 2               // reliable to all
699 #define MSG_INIT                3               // write to the init string
700
701 sizebuf_t *VM_WriteDest (void)
702 {
703         int             dest;
704         int             destclient;
705
706         if(!sv.active)
707                 PRVM_ERROR("VM_WriteDest: game is not server (%s)", PRVM_NAME);
708
709         dest = PRVM_G_FLOAT(OFS_PARM1);
710         switch (dest)
711         {
712         case MSG_BROADCAST:
713                 return &sv.datagram;
714
715         case MSG_ONE:
716                 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
717                 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active || !svs.clients[destclient].netconnection)
718                         PRVM_ERROR("VM_clientcommand: %s: invalid client !", PRVM_NAME);
719
720                 return &svs.clients[destclient].netconnection->message;
721
722         case MSG_ALL:
723                 return &sv.reliable_datagram;
724
725         case MSG_INIT:
726                 return &sv.signon;
727
728         default:
729                 PRVM_ERROR ("WriteDest: bad destination");
730                 break;
731         }
732
733         return NULL;
734 }
735
736 void VM_M_WriteByte (void)
737 {
738         MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
739 }
740
741 void VM_M_WriteChar (void)
742 {
743         MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
744 }
745
746 void VM_M_WriteShort (void)
747 {
748         MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
749 }
750
751 void VM_M_WriteLong (void)
752 {
753         MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
754 }
755
756 void VM_M_WriteAngle (void)
757 {
758         MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
759 }
760
761 void VM_M_WriteCoord (void)
762 {
763         MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
764 }
765
766 void VM_M_WriteString (void)
767 {
768         MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
769 }
770
771 void VM_M_WriteEntity (void)
772 {
773         MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
774 }
775
776 prvm_builtin_t vm_m_builtins[] = {
777         0, // to be consistent with the old vm
778         // common builtings (mostly)
779         VM_checkextension,
780         VM_error,
781         VM_objerror,
782         VM_print,
783         VM_bprint,
784         VM_sprint,
785         VM_centerprint,
786         VM_normalize,
787         VM_vlen,
788         VM_vectoyaw,    // #10
789         VM_vectoangles,
790         VM_random,
791         VM_localcmd,
792         VM_cvar,
793         VM_cvar_set,
794         VM_dprint,
795         VM_ftos,
796         VM_fabs,
797         VM_vtos,
798         VM_etos,                // 20
799         VM_stof,
800         VM_spawn,
801         VM_remove,
802         VM_find,
803         VM_findfloat,
804         VM_findchain,
805         VM_findchainfloat,
806         VM_M_precache_file,
807         VM_M_precache_sound,
808         VM_coredump,    // 30
809         VM_traceon,
810         VM_traceoff,
811         VM_eprint,
812         VM_rint,
813         VM_floor,
814         VM_ceil,
815         VM_nextent,
816         VM_sin,
817         VM_cos,
818         VM_sqrt,                // 40
819         VM_randomvec,
820         VM_registercvar,
821         VM_min,
822         VM_max,
823         VM_bound,
824         VM_pow,
825         VM_copyentity,
826         VM_fopen,
827         VM_fclose,
828         VM_fgets,               // 50
829         VM_fputs,
830         VM_strlen,
831         VM_strcat,
832         VM_substring,
833         VM_stov,
834         VM_strzone,
835         VM_strunzone,
836         VM_tokenize,
837         VM_argv,
838         VM_isserver,    // 60
839         VM_clientcount,
840         VM_clientstate,
841         VM_clcommand,
842         VM_changelevel,
843         VM_localsound,
844         VM_getmousepos,
845         VM_gettime,
846         VM_loadfromdata,
847         VM_loadfromfile,
848         VM_modulo,              // 70
849         VM_cvar_string,
850         VM_crash,
851         VM_stackdump,   // 73
852         VM_search_begin,
853         VM_search_end,
854         VM_search_getsize,
855         VM_search_getfilename, // 77
856         VM_chr,
857         VM_itof,
858         VM_ftoi,                // 80
859         VM_itof,                // isString
860         VM_altstr_count,
861         VM_altstr_prepare,
862         VM_altstr_get,
863         VM_altstr_set,
864         VM_altstr_ins,
865         VM_findflags,
866         VM_findchainflags,
867         VM_cvar_defstring, // 89
868         0, // 90
869         e10,                    // 100
870         e100,                   // 200
871         e100,                   // 300
872         e100,                   // 400
873         // msg functions
874         VM_M_WriteByte,
875         VM_M_WriteChar,
876         VM_M_WriteShort,
877         VM_M_WriteLong,
878         VM_M_WriteAngle,
879         VM_M_WriteCoord,
880         VM_M_WriteString,
881         VM_M_WriteEntity,       // 408
882         0,
883         0,                              // 410
884         e10,                    // 420
885         e10,                    // 430
886         e10,                    // 440
887         e10,                    // 450
888         // draw functions
889         VM_iscachedpic,
890         VM_precache_pic,
891         VM_freepic,
892         VM_drawcharacter,
893         VM_drawstring,
894         VM_drawpic,
895         VM_drawfill,
896         VM_drawsetcliparea,
897         VM_drawresetcliparea,
898         VM_getimagesize,// 460
899         VM_cin_open,
900         VM_cin_close,
901         VM_cin_setstate,
902         VM_cin_getstate,
903         VM_cin_restart, // 465
904         VM_drawline,    // 466
905         0,0,0,0,        // 470
906         e10,                    // 480
907         e10,                    // 490
908         e10,                    // 500
909         e100,                   // 600
910         // menu functions
911         VM_M_setkeydest,
912         VM_M_getkeydest,
913         VM_M_setmousetarget,
914         VM_M_getmousetarget,
915         VM_M_callfunction,
916         VM_M_writetofile,
917         VM_M_isfunction,
918         VM_M_getresolution,
919         VM_keynumtostring,
920         VM_M_findkeysforcommand,// 610
921         VM_M_getserverliststat,
922         VM_M_getserverliststring,
923         VM_parseentitydata,
924         VM_stringtokeynum,
925         VM_M_resetserverlistmasks,
926         VM_M_setserverlistmaskstring,
927         VM_M_setserverlistmasknumber,
928         VM_M_resortserverlist,
929         VM_M_setserverlistsort,
930         VM_M_refreshserverlist,
931         VM_M_getserverlistnumber,
932         VM_M_getserverlistindexforkey,
933         VM_M_addwantedserverlistkey // 623
934 };
935
936 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
937
938 void VM_M_Cmd_Init(void)
939 {
940         VM_Cmd_Init();
941 }
942
943 void VM_M_Cmd_Reset(void)
944 {
945         //VM_Cmd_Init();
946         VM_Cmd_Reset();
947 }