]> icculus.org git repositories - divverent/darkplaces.git/blob - pr_edict.c
replaced CL_PointQ1Contents with longer calls to contents conversion and CL_PointSupe...
[divverent/darkplaces.git] / pr_edict.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // sv_edict.c -- entity dictionary
21
22 #include "quakedef.h"
23
24 dprograms_t             *progs;
25 mfunction_t             *prog->functions;
26 char                    *pr_strings;
27 int                             pr_stringssize;
28 ddef_t                  *pr_fielddefs;
29 ddef_t                  *pr_globaldefs;
30 dstatement_t    *pr_statements;
31 globalvars_t    *pr_global_struct;
32 float                   *pr_globals;                    // same as pr_global_struct
33 int                             prog->edict_size;                       // in bytes
34 int                             pr_edictareasize;               // LordHavoc: in bytes
35
36 int                             pr_maxknownstrings;
37 int                             pr_numknownstrings;
38 const char              **pr_knownstrings;
39
40 unsigned short  pr_crc;
41
42 mempool_t               *serverprogs_mempool;
43
44 int             type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
45
46 ddef_t *ED_FieldAtOfs(int ofs);
47 qboolean ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s);
48
49 cvar_t  pr_checkextension = {CVAR_READONLY, "pr_checkextension", "1"};
50 cvar_t  nomonsters = {0, "nomonsters", "0"};
51 cvar_t  gamecfg = {0, "gamecfg", "0"};
52 cvar_t  scratch1 = {0, "scratch1", "0"};
53 cvar_t  scratch2 = {0,"scratch2", "0"};
54 cvar_t  scratch3 = {0, "scratch3", "0"};
55 cvar_t  scratch4 = {0, "scratch4", "0"};
56 cvar_t  savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0"};
57 cvar_t  saved1 = {CVAR_SAVE, "saved1", "0"};
58 cvar_t  saved2 = {CVAR_SAVE, "saved2", "0"};
59 cvar_t  saved3 = {CVAR_SAVE, "saved3", "0"};
60 cvar_t  saved4 = {CVAR_SAVE, "saved4", "0"};
61 cvar_t  decors = {0, "decors", "0"};
62 cvar_t  nehx00 = {0, "nehx00", "0"};cvar_t      nehx01 = {0, "nehx01", "0"};
63 cvar_t  nehx02 = {0, "nehx02", "0"};cvar_t      nehx03 = {0, "nehx03", "0"};
64 cvar_t  nehx04 = {0, "nehx04", "0"};cvar_t      nehx05 = {0, "nehx05", "0"};
65 cvar_t  nehx06 = {0, "nehx06", "0"};cvar_t      nehx07 = {0, "nehx07", "0"};
66 cvar_t  nehx08 = {0, "nehx08", "0"};cvar_t      nehx09 = {0, "nehx09", "0"};
67 cvar_t  nehx10 = {0, "nehx10", "0"};cvar_t      nehx11 = {0, "nehx11", "0"};
68 cvar_t  nehx12 = {0, "nehx12", "0"};cvar_t      nehx13 = {0, "nehx13", "0"};
69 cvar_t  nehx14 = {0, "nehx14", "0"};cvar_t      nehx15 = {0, "nehx15", "0"};
70 cvar_t  nehx16 = {0, "nehx16", "0"};cvar_t      nehx17 = {0, "nehx17", "0"};
71 cvar_t  nehx18 = {0, "nehx18", "0"};cvar_t      nehx19 = {0, "nehx19", "0"};
72 cvar_t  cutscene = {0, "cutscene", "1"};
73 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
74 cvar_t  pr_boundscheck = {0, "pr_boundscheck", "1"};
75 // LordHavoc: prints every opcode as it executes - warning: this is significant spew
76 cvar_t  pr_traceqc = {0, "pr_traceqc", "0"};
77
78 ddef_t *ED_FindField (const char *name);
79 mfunction_t *PRVM_ED_FindFunction (const char *name);
80
81 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue...  these are defined as externs in progs.h
82 int eval_gravity;
83 int eval_button3;
84 int eval_button4;
85 int eval_button5;
86 int eval_button6;
87 int eval_button7;
88 int eval_button8;
89 int eval_buttonuse;
90 int eval_buttonchat;
91 int eval_glow_size;
92 int eval_glow_trail;
93 int eval_glow_color;
94 int eval_items2;
95 int eval_scale;
96 int eval_alpha;
97 int eval_renderamt; // HalfLife support
98 int eval_rendermode; // HalfLife support
99 int eval_fullbright;
100 int eval_ammo_shells1;
101 int eval_ammo_nails1;
102 int eval_ammo_lava_nails;
103 int eval_ammo_rockets1;
104 int eval_ammo_multi_rockets;
105 int eval_ammo_cells1;
106 int eval_ammo_plasma;
107 int eval_idealpitch;
108 int eval_pitch_speed;
109 int eval_viewmodelforclient;
110 int eval_nodrawtoclient;
111 int eval_exteriormodeltoclient;
112 int eval_drawonlytoclient;
113 int eval_ping;
114 int eval_movement;
115 int eval_pmodel;
116 int eval_punchvector;
117 int eval_viewzoom;
118 int eval_clientcolors;
119 int eval_tag_entity;
120 int eval_tag_index;
121 int eval_light_lev;
122 int eval_color;
123 int eval_style;
124 int eval_pflags;
125 int eval_cursor_active;
126 int eval_cursor_screen;
127 int eval_cursor_trace_start;
128 int eval_cursor_trace_endpos;
129 int eval_cursor_trace_ent;
130 int eval_colormod;
131 int eval_playermodel;
132 int eval_playerskin;
133
134 mfunction_t *SV_PlayerPhysicsQC;
135 mfunction_t *EndFrameQC;
136 //KrimZon - SERVER COMMANDS IN QUAKEC
137 mfunction_t *SV_ParseClientCommandQC;
138
139 int FindFieldOffset(const char *field)
140 {
141         ddef_t *d;
142         d = ED_FindField(field);
143         if (!d)
144                 return 0;
145         return d->ofs*4;
146 }
147
148 void FindEdictFieldOffsets(void)
149 {
150         eval_gravity = FindFieldOffset("gravity");
151         eval_button3 = FindFieldOffset("button3");
152         eval_button4 = FindFieldOffset("button4");
153         eval_button5 = FindFieldOffset("button5");
154         eval_button6 = FindFieldOffset("button6");
155         eval_button7 = FindFieldOffset("button7");
156         eval_button8 = FindFieldOffset("button8");
157         eval_buttonuse = FindFieldOffset("buttonuse");
158         eval_buttonchat = FindFieldOffset("buttonchat");
159         eval_glow_size = FindFieldOffset("glow_size");
160         eval_glow_trail = FindFieldOffset("glow_trail");
161         eval_glow_color = FindFieldOffset("glow_color");
162         eval_items2 = FindFieldOffset("items2");
163         eval_scale = FindFieldOffset("scale");
164         eval_alpha = FindFieldOffset("alpha");
165         eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
166         eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
167         eval_fullbright = FindFieldOffset("fullbright");
168         eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
169         eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
170         eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
171         eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
172         eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
173         eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
174         eval_ammo_plasma = FindFieldOffset("ammo_plasma");
175         eval_idealpitch = FindFieldOffset("idealpitch");
176         eval_pitch_speed = FindFieldOffset("pitch_speed");
177         eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
178         eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
179         eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
180         eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
181         eval_ping = FindFieldOffset("ping");
182         eval_movement = FindFieldOffset("movement");
183         eval_pmodel = FindFieldOffset("pmodel");
184         eval_punchvector = FindFieldOffset("punchvector");
185         eval_viewzoom = FindFieldOffset("viewzoom");
186         eval_clientcolors = FindFieldOffset("clientcolors");
187         eval_tag_entity = FindFieldOffset("tag_entity");
188         eval_tag_index = FindFieldOffset("tag_index");
189         eval_light_lev = FindFieldOffset("light_lev");
190         eval_color = FindFieldOffset("color");
191         eval_style = FindFieldOffset("style");
192         eval_pflags = FindFieldOffset("pflags");
193         eval_cursor_active = FindFieldOffset("cursor_active");
194         eval_cursor_screen = FindFieldOffset("cursor_screen");
195         eval_cursor_trace_start = FindFieldOffset("cursor_trace_start");
196         eval_cursor_trace_endpos = FindFieldOffset("cursor_trace_endpos");
197         eval_cursor_trace_ent = FindFieldOffset("cursor_trace_ent");
198         eval_colormod = FindFieldOffset("colormod");
199         eval_playermodel = FindFieldOffset("playermodel");
200         eval_playerskin = FindFieldOffset("playerskin");
201
202         // LordHavoc: allowing QuakeC to override the player movement code
203         SV_PlayerPhysicsQC = PRVM_ED_FindFunction ("SV_PlayerPhysics");
204         // LordHavoc: support for endframe
205         EndFrameQC = PRVM_ED_FindFunction ("EndFrame");
206         //KrimZon - SERVER COMMANDS IN QUAKEC
207         SV_ParseClientCommandQC = PRVM_ED_FindFunction ("SV_ParseClientCommand");
208 }
209
210 /*
211 =================
212 ED_ClearEdict
213
214 Sets everything to NULL
215 =================
216 */
217 void ED_ClearEdict (prvm_edict_t *e)
218 {
219         int num;
220         memset (e->v, 0, progs->entityfields * 4);
221         e->priv.server->free = false;
222         // LordHavoc: for consistency set these here
223         num = PRVM_NUM_FOR_EDICT(e) - 1;
224         if (num >= 0 && num < svs.maxclients)
225         {
226                 prvm_eval_t *val;
227                 // set colormap and team on newly created player entity
228                 e->fields.server->colormap = num + 1;
229                 e->fields.server->team = (svs.clients[num].colors & 15) + 1;
230                 // set netname/clientcolors back to client values so that
231                 // DP_SV_CLIENTNAME and DPV_SV_CLIENTCOLORS will not immediately
232                 // reset them
233                 e->fields.server->netname = PRVM_SetEngineString(svs.clients[num].name);
234                 if ((val = PRVM_GETEDICTFIELDVALUE(e, eval_clientcolors)))
235                         val->_float = svs.clients[num].colors;
236                 // NEXUIZ_PLAYERMODEL and NEXUIZ_PLAYERSKIN
237                 if( eval_playermodel )
238                         PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PRVM_SetEngineString(svs.clients[num].playermodel);
239                 if( eval_playerskin )
240                         PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PRVM_SetEngineString(svs.clients[num].playerskin);
241         }
242 }
243
244 /*
245 =================
246 ED_Alloc
247
248 Either finds a free edict, or allocates a new one.
249 Try to avoid reusing an entity that was recently freed, because it
250 can cause the client to think the entity morphed into something else
251 instead of being removed and recreated, which can cause interpolated
252 angles and bad trails.
253 =================
254 */
255 prvm_edict_t *ED_Alloc (void)
256 {
257         int                     i;
258         prvm_edict_t            *e;
259
260         for (i = svs.maxclients + 1;i < prog->num_edicts;i++)
261         {
262                 e = PRVM_EDICT_NUM(i);
263                 // the first couple seconds of server time can involve a lot of
264                 // freeing and allocating, so relax the replacement policy
265                 if (e->priv.server->free && ( e->priv.server->freetime < 2 || sv.time - e->priv.server->freetime > 0.5 ) )
266                 {
267                         ED_ClearEdict (e);
268                         return e;
269                 }
270         }
271
272         if (i == MAX_EDICTS)
273                 Host_Error ("ED_Alloc: no free edicts");
274
275         prog->num_edicts++;
276         if (prog->num_edicts >= prog->max_edicts)
277                 SV_IncreaseEdicts();
278         e = PRVM_EDICT_NUM(i);
279         ED_ClearEdict (e);
280
281         return e;
282 }
283
284 /*
285 =================
286 ED_Free
287
288 Marks the edict as free
289 FIXME: walk all entities and NULL out references to this entity
290 =================
291 */
292 void ED_Free (prvm_edict_t *ed)
293 {
294         SV_UnlinkEdict (ed);            // unlink from world bsp
295
296         ed->priv.server->free = true;
297         ed->fields.server->model = 0;
298         ed->fields.server->takedamage = 0;
299         ed->fields.server->modelindex = 0;
300         ed->fields.server->colormap = 0;
301         ed->fields.server->skin = 0;
302         ed->fields.server->frame = 0;
303         VectorClear(ed->fields.server->origin);
304         VectorClear(ed->fields.server->angles);
305         ed->fields.server->nextthink = -1;
306         ed->fields.server->solid = 0;
307
308         ed->priv.server->freetime = sv.time;
309 }
310
311 //===========================================================================
312
313 /*
314 ============
315 ED_GlobalAtOfs
316 ============
317 */
318 ddef_t *ED_GlobalAtOfs (int ofs)
319 {
320         ddef_t          *def;
321         int                     i;
322
323         for (i=0 ; i<progs->numglobaldefs ; i++)
324         {
325                 def = &pr_globaldefs[i];
326                 if (def->ofs == ofs)
327                         return def;
328         }
329         return NULL;
330 }
331
332 /*
333 ============
334 ED_FieldAtOfs
335 ============
336 */
337 ddef_t *ED_FieldAtOfs (int ofs)
338 {
339         ddef_t          *def;
340         int                     i;
341
342         for (i=0 ; i<progs->numfielddefs ; i++)
343         {
344                 def = &pr_fielddefs[i];
345                 if (def->ofs == ofs)
346                         return def;
347         }
348         return NULL;
349 }
350
351 /*
352 ============
353 ED_FindField
354 ============
355 */
356 ddef_t *ED_FindField (const char *name)
357 {
358         ddef_t *def;
359         int i;
360
361         for (i=0 ; i<progs->numfielddefs ; i++)
362         {
363                 def = &pr_fielddefs[i];
364                 if (!strcmp(PRVM_GetString(def->s_name), name))
365                         return def;
366         }
367         return NULL;
368 }
369
370 /*
371 ============
372 ED_FindGlobal
373 ============
374 */
375 ddef_t *ED_FindGlobal (const char *name)
376 {
377         ddef_t *def;
378         int i;
379
380         for (i=0 ; i<progs->numglobaldefs ; i++)
381         {
382                 def = &pr_globaldefs[i];
383                 if (!strcmp(PRVM_GetString(def->s_name), name))
384                         return def;
385         }
386         return NULL;
387 }
388
389
390 /*
391 ============
392 PRVM_ED_FindFunction
393 ============
394 */
395 mfunction_t *PRVM_ED_FindFunction (const char *name)
396 {
397         mfunction_t             *func;
398         int                             i;
399
400         for (i=0 ; i<progs->numfunctions ; i++)
401         {
402                 func = &prog->functions[i];
403                 if (!strcmp(PRVM_GetString(func->s_name), name))
404                         return func;
405         }
406         return NULL;
407 }
408
409
410 /*
411 ============
412 PR_ValueString
413
414 Returns a string describing *data in a type specific manner
415 =============
416 */
417 //int NoCrash_NUM_FOR_EDICT(prvm_edict_t *e);
418 char *PR_ValueString (etype_t type, prvm_eval_t *val)
419 {
420         static char line[1024]; // LordHavoc: enlarged a bit (was 256)
421         ddef_t *def;
422         mfunction_t *f;
423         int n;
424
425         type &= ~DEF_SAVEGLOBAL;
426
427         switch (type)
428         {
429         case ev_string:
430                 strlcpy (line, PRVM_GetString (val->string), sizeof (line));
431                 break;
432         case ev_entity:
433                 //n = NoCrash_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict));
434                 n = val->edict;
435                 if (n < 0 || n >= MAX_EDICTS)
436                         dpsnprintf (line, sizeof (line), "entity %i (invalid!)", n);
437                 else
438                         dpsnprintf (line, sizeof (line), "entity %i", n);
439                 break;
440         case ev_function:
441                 f = prog->functions + val->function;
442                 dpsnprintf (line, sizeof (line), "%s()", PRVM_GetString(f->s_name));
443                 break;
444         case ev_field:
445                 def = ED_FieldAtOfs ( val->_int );
446                 dpsnprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
447                 break;
448         case ev_void:
449                 dpsnprintf (line, sizeof (line), "void");
450                 break;
451         case ev_float:
452                 // LordHavoc: changed from %5.1f to %10.4f
453                 dpsnprintf (line, sizeof (line), "%10.4f", val->_float);
454                 break;
455         case ev_vector:
456                 // LordHavoc: changed from %5.1f to %10.4f
457                 dpsnprintf (line, sizeof (line), "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
458                 break;
459         case ev_pointer:
460                 dpsnprintf (line, sizeof (line), "pointer");
461                 break;
462         default:
463                 dpsnprintf (line, sizeof (line), "bad type %i", type);
464                 break;
465         }
466
467         return line;
468 }
469
470 /*
471 ============
472 PR_UglyValueString
473
474 Returns a string describing *data in a type specific manner
475 Easier to parse than PR_ValueString
476 =============
477 */
478 char *PR_UglyValueString (etype_t type, prvm_eval_t *val)
479 {
480         static char line[4096];
481         int i;
482         const char *s;
483         ddef_t *def;
484         mfunction_t *f;
485
486         type &= ~DEF_SAVEGLOBAL;
487
488         switch (type)
489         {
490         case ev_string:
491                 // Parse the string a bit to turn special characters
492                 // (like newline, specifically) into escape codes,
493                 // this fixes saving games from various mods
494                 s = PRVM_GetString (val->string);
495                 for (i = 0;i < (int)sizeof(line) - 2 && *s;)
496                 {
497                         if (*s == '\n')
498                         {
499                                 line[i++] = '\\';
500                                 line[i++] = 'n';
501                         }
502                         else if (*s == '\r')
503                         {
504                                 line[i++] = '\\';
505                                 line[i++] = 'r';
506                         }
507                         else
508                                 line[i++] = *s;
509                         s++;
510                 }
511                 line[i] = '\0';
512                 break;
513         case ev_entity:
514                 dpsnprintf (line, sizeof (line), "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
515                 break;
516         case ev_function:
517                 f = prog->functions + val->function;
518                 strlcpy (line, PRVM_GetString (f->s_name), sizeof (line));
519                 break;
520         case ev_field:
521                 def = ED_FieldAtOfs ( val->_int );
522                 dpsnprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
523                 break;
524         case ev_void:
525                 dpsnprintf (line, sizeof (line), "void");
526                 break;
527         case ev_float:
528                 dpsnprintf (line, sizeof (line), "%f", val->_float);
529                 break;
530         case ev_vector:
531                 dpsnprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
532                 break;
533         default:
534                 dpsnprintf (line, sizeof (line), "bad type %i", type);
535                 break;
536         }
537
538         return line;
539 }
540
541 /*
542 ============
543 PR_GlobalString
544
545 Returns a string with a description and the contents of a global,
546 padded to 20 field width
547 ============
548 */
549 char *PR_GlobalString (int ofs)
550 {
551         char    *s;
552         int             i;
553         ddef_t  *def;
554         void    *val;
555         static char     line[128];
556
557         val = (void *)&pr_globals[ofs];
558         def = ED_GlobalAtOfs(ofs);
559         if (!def)
560                 dpsnprintf (line, sizeof (line), "%i(?)", ofs);
561         else
562         {
563                 s = PR_ValueString (def->type, val);
564                 dpsnprintf (line, sizeof (line), "%i(%s)%s", ofs, PRVM_GetString(def->s_name), s);
565         }
566
567         i = strlen(line);
568         for ( ; i<20 ; i++)
569                 strlcat (line, " ", sizeof (line));
570         strlcat (line, " ", sizeof (line));
571
572         return line;
573 }
574
575 char *PR_GlobalStringNoContents (int ofs)
576 {
577         int             i;
578         ddef_t  *def;
579         static char     line[128];
580
581         def = ED_GlobalAtOfs(ofs);
582         if (!def)
583                 dpsnprintf (line, sizeof (line), "%i(?)", ofs);
584         else
585                 dpsnprintf (line, sizeof (line), "%i(%s)", ofs, PRVM_GetString(def->s_name));
586
587         i = strlen(line);
588         for ( ; i<20 ; i++)
589                 strlcat (line, " ", sizeof (line));
590         strlcat (line, " ", sizeof (line));
591
592         return line;
593 }
594
595
596 /*
597 =============
598 ED_Print
599
600 For debugging
601 =============
602 */
603 // LordHavoc: optimized this to print out much more quickly (tempstring)
604 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
605 void ED_Print(prvm_edict_t *ed)
606 {
607         int             l;
608         ddef_t  *d;
609         int             *v;
610         int             i, j;
611         const char      *name;
612         int             type;
613         char    tempstring[8192], tempstring2[260]; // temporary string buffers
614
615         if (ed->priv.server->free)
616         {
617                 Con_Print("FREE\n");
618                 return;
619         }
620
621         tempstring[0] = 0;
622         dpsnprintf (tempstring, sizeof (tempstring), "\nEDICT %i:\n", PRVM_NUM_FOR_EDICT(ed));
623         for (i=1 ; i<progs->numfielddefs ; i++)
624         {
625                 d = &pr_fielddefs[i];
626                 name = PRVM_GetString(d->s_name);
627                 if (name[strlen(name)-2] == '_')
628                         continue;       // skip _x, _y, _z vars
629
630                 v = (int *)((char *)ed->v + d->ofs*4);
631
632         // if the value is still all 0, skip the field
633                 type = d->type & ~DEF_SAVEGLOBAL;
634
635                 for (j=0 ; j<type_size[type] ; j++)
636                         if (v[j])
637                                 break;
638                 if (j == type_size[type])
639                         continue;
640
641                 if (strlen(name) > 256)
642                 {
643                         memcpy (tempstring2, name, 256);
644                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
645                         tempstring2[259] = 0;
646                         name = tempstring2;
647                 }
648                 strlcat (tempstring, name, sizeof (tempstring));
649                 for (l = strlen(name);l < 14;l++)
650                         strcat(tempstring, " ");
651                 strcat(tempstring, " ");
652
653                 name = PR_ValueString(d->type, (prvm_eval_t *)v);
654                 if (strlen(name) > 256)
655                 {
656                         memcpy(tempstring2, name, 256);
657                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
658                         tempstring2[259] = 0;
659                         name = tempstring2;
660                 }
661                 strlcat (tempstring, name, sizeof (tempstring));
662                 strlcat (tempstring, "\n", sizeof (tempstring));
663                 if (strlen(tempstring) >= 4096)
664                 {
665                         Con_Print(tempstring);
666                         tempstring[0] = 0;
667                 }
668         }
669         if (tempstring[0])
670                 Con_Print(tempstring);
671 }
672
673 /*
674 =============
675 ED_Write
676
677 For savegames
678 =============
679 */
680 void ED_Write (qfile_t *f, prvm_edict_t *ed)
681 {
682         ddef_t  *d;
683         int             *v;
684         int             i, j;
685         const char      *name;
686         int             type;
687
688         FS_Print(f, "{\n");
689
690         if (ed->priv.server->free)
691         {
692                 FS_Print(f, "}\n");
693                 return;
694         }
695
696         for (i=1 ; i<progs->numfielddefs ; i++)
697         {
698                 d = &pr_fielddefs[i];
699                 name = PRVM_GetString(d->s_name);
700                 if (name[strlen(name)-2] == '_')
701                         continue;       // skip _x, _y, _z vars
702
703                 v = (int *)((char *)ed->v + d->ofs*4);
704
705         // if the value is still all 0, skip the field
706                 type = d->type & ~DEF_SAVEGLOBAL;
707                 for (j=0 ; j<type_size[type] ; j++)
708                         if (v[j])
709                                 break;
710                 if (j == type_size[type])
711                         continue;
712
713                 FS_Printf(f,"\"%s\" ",name);
714                 FS_Printf(f,"\"%s\"\n", PR_UglyValueString(d->type, (prvm_eval_t *)v));
715         }
716
717         FS_Print(f, "}\n");
718 }
719
720 void ED_PrintNum (int ent)
721 {
722         ED_Print(PRVM_EDICT_NUM(ent));
723 }
724
725 /*
726 =============
727 ED_PrintEdicts
728
729 For debugging, prints all the entities in the current server
730 =============
731 */
732 void ED_PrintEdicts (void)
733 {
734         int             i;
735
736         Con_Printf("%i entities\n", prog->num_edicts);
737         for (i=0 ; i<prog->num_edicts ; i++)
738                 ED_PrintNum (i);
739 }
740
741 /*
742 =============
743 ED_PrintEdict_f
744
745 For debugging, prints a single edict
746 =============
747 */
748 void ED_PrintEdict_f (void)
749 {
750         int             i;
751
752         i = atoi (Cmd_Argv(1));
753         if (i < 0 || i >= prog->num_edicts)
754         {
755                 Con_Print("Bad edict number\n");
756                 return;
757         }
758         ED_PrintNum (i);
759 }
760
761 /*
762 =============
763 ED_Count
764
765 For debugging
766 =============
767 */
768 void ED_Count (void)
769 {
770         int             i;
771         prvm_edict_t    *ent;
772         int             active, models, solid, step;
773
774         active = models = solid = step = 0;
775         for (i=0 ; i<prog->num_edicts ; i++)
776         {
777                 ent = PRVM_EDICT_NUM(i);
778                 if (ent->priv.server->free)
779                         continue;
780                 active++;
781                 if (ent->fields.server->solid)
782                         solid++;
783                 if (ent->fields.server->model)
784                         models++;
785                 if (ent->fields.server->movetype == MOVETYPE_STEP)
786                         step++;
787         }
788
789         Con_Printf("num_edicts:%3i\n", prog->num_edicts);
790         Con_Printf("active    :%3i\n", active);
791         Con_Printf("view      :%3i\n", models);
792         Con_Printf("touch     :%3i\n", solid);
793         Con_Printf("step      :%3i\n", step);
794
795 }
796
797 /*
798 ==============================================================================
799
800                                         ARCHIVING GLOBALS
801
802 FIXME: need to tag constants, doesn't really work
803 ==============================================================================
804 */
805
806 /*
807 =============
808 ED_WriteGlobals
809 =============
810 */
811 void ED_WriteGlobals (qfile_t *f)
812 {
813         ddef_t          *def;
814         int                     i;
815         const char              *name;
816         int                     type;
817
818         FS_Print(f,"{\n");
819         for (i=0 ; i<progs->numglobaldefs ; i++)
820         {
821                 def = &pr_globaldefs[i];
822                 type = def->type;
823                 if ( !(def->type & DEF_SAVEGLOBAL) )
824                         continue;
825                 type &= ~DEF_SAVEGLOBAL;
826
827                 if (type != ev_string && type != ev_float && type != ev_entity)
828                         continue;
829
830                 name = PRVM_GetString(def->s_name);
831                 FS_Printf(f,"\"%s\" ", name);
832                 FS_Printf(f,"\"%s\"\n", PR_UglyValueString(type, (prvm_eval_t *)&pr_globals[def->ofs]));
833         }
834         FS_Print(f,"}\n");
835 }
836
837 /*
838 =============
839 ED_EdictSet_f
840
841 Console command to set a field of a specified edict
842 =============
843 */
844 void ED_EdictSet_f(void)
845 {
846         prvm_edict_t *ed;
847         ddef_t *key;
848
849         if(Cmd_Argc() != 4)
850         {
851                 Con_Print("edictset <edict number> <field> <value>\n");
852                 return;
853         }
854         ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(1)));
855
856         if((key = ED_FindField(Cmd_Argv(2))) == 0)
857         {
858                 Con_Printf("Key %s not found !\n", Cmd_Argv(2));
859                 return;
860         }
861
862         ED_ParseEpair(ed, key, Cmd_Argv(3));
863 }
864
865 /*
866 =============
867 ED_ParseGlobals
868 =============
869 */
870 void ED_ParseGlobals (const char *data)
871 {
872         char keyname[1024]; // LordHavoc: good idea? bad idea?  was 64
873         ddef_t *key;
874
875         while (1)
876         {
877                 // parse key
878                 if (!COM_ParseToken(&data, false))
879                         Host_Error ("ED_ParseEntity: EOF without closing brace");
880                 if (com_token[0] == '}')
881                         break;
882
883                 strcpy (keyname, com_token);
884
885                 // parse value
886                 if (!COM_ParseToken(&data, false))
887                         Host_Error ("ED_ParseEntity: EOF without closing brace");
888
889                 if (com_token[0] == '}')
890                         Host_Error ("ED_ParseEntity: closing brace without data");
891
892                 key = ED_FindGlobal (keyname);
893                 if (!key)
894                 {
895                         Con_DPrintf("'%s' is not a global\n", keyname);
896                         continue;
897                 }
898
899                 if (!ED_ParseEpair(NULL, key, com_token))
900                         Host_Error ("ED_ParseGlobals: parse error");
901         }
902 }
903
904 //============================================================================
905
906
907 /*
908 =============
909 ED_ParseEval
910
911 Can parse either fields or globals
912 returns false if error
913 =============
914 */
915 qboolean ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
916 {
917         int i, l;
918         char *new_p;
919         ddef_t *def;
920         prvm_eval_t *val;
921         mfunction_t *func;
922
923         if (ent)
924                 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
925         else
926                 val = (prvm_eval_t *)((int *)pr_globals + key->ofs);
927         switch (key->type & ~DEF_SAVEGLOBAL)
928         {
929         case ev_string:
930                 l = strlen(s) + 1;
931                 new_p = PR_AllocString(l);
932                 val->string = PR_SetQCString(new_p);
933                 for (i = 0;i < l;i++)
934                 {
935                         if (s[i] == '\\' && i < l-1)
936                         {
937                                 i++;
938                                 if (s[i] == 'n')
939                                         *new_p++ = '\n';
940                                 else if (s[i] == 'r')
941                                         *new_p++ = '\r';
942                                 else
943                                         *new_p++ = s[i];
944                         }
945                         else
946                                 *new_p++ = s[i];
947                 }
948                 break;
949
950         case ev_float:
951                 while (*s && *s <= ' ')
952                         s++;
953                 val->_float = atof(s);
954                 break;
955
956         case ev_vector:
957                 for (i = 0;i < 3;i++)
958                 {
959                         while (*s && *s <= ' ')
960                                 s++;
961                         if (*s)
962                                 val->vector[i] = atof(s);
963                         else
964                                 val->vector[i] = 0;
965                         while (*s > ' ')
966                                 s++;
967                 }
968                 break;
969
970         case ev_entity:
971                 while (*s && *s <= ' ')
972                         s++;
973                 i = atoi(s);
974                 if (i < 0 || i >= MAX_EDICTS)
975                         Con_Printf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
976                 while (i >= prog->max_edicts)
977                         SV_IncreaseEdicts();
978                 // if SV_IncreaseEdicts was called the base pointer needs to be updated
979                 if (ent)
980                         val = (prvm_eval_t *)((int *)ent->v + key->ofs);
981                 val->edict = PRVM_EDICT_TO_PROG(PRVM_EDICT_NUM(i));
982                 break;
983
984         case ev_field:
985                 def = ED_FindField(s);
986                 if (!def)
987                 {
988                         Con_DPrintf("ED_ParseEpair: Can't find field %s\n", s);
989                         return false;
990                 }
991                 //val->_int = PRVM_G_INT(def->ofs); // AK Please check this - seems to be an org. quake bug
992                 val->_int = def->ofs;
993                 break;
994
995         case ev_function:
996                 func = PRVM_ED_FindFunction(s);
997                 if (!func)
998                 {
999                         Con_Printf("ED_ParseEpair: Can't find function %s\n", s);
1000                         return false;
1001                 }
1002                 val->function = func - prog->functions;
1003                 break;
1004
1005         default:
1006                 Con_Printf("ED_ParseEpair: Unknown key->type %i for key \"%s\"\n", key->type, PRVM_GetString(key->s_name));
1007                 return false;
1008         }
1009         return true;
1010 }
1011
1012 /*
1013 ====================
1014 ED_ParseEdict
1015
1016 Parses an edict out of the given string, returning the new position
1017 ed should be a properly initialized empty edict.
1018 Used for initial level load and for savegames.
1019 ====================
1020 */
1021 const char *ED_ParseEdict (const char *data, prvm_edict_t *ent)
1022 {
1023         ddef_t *key;
1024         qboolean anglehack;
1025         qboolean init;
1026         char keyname[256];
1027         int n;
1028
1029         init = false;
1030
1031 // clear it
1032         if (ent != prog->edicts)        // hack
1033                 memset (ent->v, 0, progs->entityfields * 4);
1034
1035 // go through all the dictionary pairs
1036         while (1)
1037         {
1038         // parse key
1039                 if (!COM_ParseToken(&data, false))
1040                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1041                 if (com_token[0] == '}')
1042                         break;
1043
1044                 // anglehack is to allow QuakeEd to write single scalar angles
1045                 // and allow them to be turned into vectors. (FIXME...)
1046                 anglehack = !strcmp (com_token, "angle");
1047                 if (anglehack)
1048                         strlcpy (com_token, "angles", sizeof (com_token));
1049
1050                 // FIXME: change light to _light to get rid of this hack
1051                 if (!strcmp(com_token, "light"))
1052                         strlcpy (com_token, "light_lev", sizeof (com_token));   // hack for single light def
1053
1054                 strlcpy (keyname, com_token, sizeof (keyname));
1055
1056                 // another hack to fix heynames with trailing spaces
1057                 n = strlen(keyname);
1058                 while (n && keyname[n-1] == ' ')
1059                 {
1060                         keyname[n-1] = 0;
1061                         n--;
1062                 }
1063
1064         // parse value
1065                 if (!COM_ParseToken(&data, false))
1066                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1067
1068                 if (com_token[0] == '}')
1069                         Host_Error ("ED_ParseEntity: closing brace without data");
1070
1071                 init = true;
1072
1073 // keynames with a leading underscore are used for utility comments,
1074 // and are immediately discarded by quake
1075                 if (keyname[0] == '_')
1076                         continue;
1077
1078                 key = ED_FindField (keyname);
1079                 if (!key)
1080                 {
1081                         Con_DPrintf("'%s' is not a field\n", keyname);
1082                         continue;
1083                 }
1084
1085                 if (anglehack)
1086                 {
1087                         char    temp[32];
1088                         strlcpy (temp, com_token, sizeof (temp));
1089                         dpsnprintf (com_token, sizeof (com_token), "0 %s 0", temp);
1090                 }
1091
1092                 if (!ED_ParseEpair(ent, key, com_token))
1093                         Host_Error ("ED_ParseEdict: parse error");
1094         }
1095
1096         if (!init)
1097                 ent->priv.server->free = true;
1098
1099         return data;
1100 }
1101
1102
1103 /*
1104 ================
1105 ED_LoadFromFile
1106
1107 The entities are directly placed in the array, rather than allocated with
1108 ED_Alloc, because otherwise an error loading the map would have entity
1109 number references out of order.
1110
1111 Creates a server's entity / program execution context by
1112 parsing textual entity definitions out of an ent file.
1113
1114 Used for both fresh maps and savegame loads.  A fresh map would also need
1115 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1116 ================
1117 */
1118 void ED_LoadFromFile (const char *data)
1119 {
1120         prvm_edict_t *ent;
1121         int parsed, inhibited, spawned, died;
1122         mfunction_t *func;
1123
1124         ent = NULL;
1125         parsed = 0;
1126         inhibited = 0;
1127         spawned = 0;
1128         died = 0;
1129         prog->globals.server->time = sv.time;
1130
1131 // parse ents
1132         while (1)
1133         {
1134 // parse the opening brace
1135                 if (!COM_ParseToken(&data, false))
1136                         break;
1137                 if (com_token[0] != '{')
1138                         Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1139
1140                 if (!ent)
1141                         ent = PRVM_EDICT_NUM(0);
1142                 else
1143                         ent = ED_Alloc ();
1144                 data = ED_ParseEdict (data, ent);
1145                 parsed++;
1146
1147 // remove things from different skill levels or deathmatch
1148                 if (gamemode != GAME_TRANSFUSION) //Transfusion does this in QC
1149                 {
1150                         if (deathmatch.integer)
1151                         {
1152                                 if (((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1153                                 {
1154                                         ED_Free (ent);
1155                                         inhibited++;
1156                                         continue;
1157                                 }
1158                         }
1159                         else if ((current_skill <= 0 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_EASY  ))
1160                                 || (current_skill == 1 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1161                                 || (current_skill >= 2 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_HARD  )))
1162                         {
1163                                 ED_Free (ent);
1164                                 inhibited++;
1165                                 continue;
1166                         }
1167                 }
1168 //
1169 // immediately call spawn function
1170 //
1171                 if (!ent->fields.server->classname)
1172                 {
1173                         Con_Print("No classname for:\n");
1174                         ED_Print(ent);
1175                         ED_Free (ent);
1176                         continue;
1177                 }
1178
1179         // look for the spawn function
1180                 func = PRVM_ED_FindFunction (PRVM_GetString(ent->fields.server->classname));
1181
1182                 if (!func)
1183                 {
1184                         if (developer.integer) // don't confuse non-developers with errors
1185                         {
1186                                 Con_Print("No spawn function for:\n");
1187                                 ED_Print(ent);
1188                         }
1189                         ED_Free (ent);
1190                         continue;
1191                 }
1192
1193                 prog->globals.server->self = PRVM_EDICT_TO_PROG(ent);
1194                 PRVM_ExecuteProgram (func - prog->functions, "QC function spawn is missing");
1195                 spawned++;
1196                 if (ent->priv.server->free)
1197                         died++;
1198         }
1199
1200         Con_DPrintf("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1201 }
1202
1203
1204 typedef struct dpfield_s
1205 {
1206         int type;
1207         char *string;
1208 }
1209 dpfield_t;
1210
1211 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1212
1213 dpfield_t dpfields[] =
1214 {
1215         {ev_entity, "cursor_trace_ent"},
1216         {ev_entity, "drawonlytoclient"},
1217         {ev_entity, "exteriormodeltoclient"},
1218         {ev_entity, "nodrawtoclient"},
1219         {ev_entity, "tag_entity"},
1220         {ev_entity, "viewmodelforclient"},
1221         {ev_float, "alpha"},
1222         {ev_float, "ammo_cells1"},
1223         {ev_float, "ammo_lava_nails"},
1224         {ev_float, "ammo_multi_rockets"},
1225         {ev_float, "ammo_nails1"},
1226         {ev_float, "ammo_plasma"},
1227         {ev_float, "ammo_rockets1"},
1228         {ev_float, "ammo_shells1"},
1229         {ev_float, "button3"},
1230         {ev_float, "button4"},
1231         {ev_float, "button5"},
1232         {ev_float, "button6"},
1233         {ev_float, "button7"},
1234         {ev_float, "button8"},
1235         {ev_float, "buttonchat"},
1236         {ev_float, "buttonuse"},
1237         {ev_float, "clientcolors"},
1238         {ev_float, "cursor_active"},
1239         {ev_float, "fullbright"},
1240         {ev_float, "glow_color"},
1241         {ev_float, "glow_size"},
1242         {ev_float, "glow_trail"},
1243         {ev_float, "gravity"},
1244         {ev_float, "idealpitch"},
1245         {ev_float, "items2"},
1246         {ev_float, "light_lev"},
1247         {ev_float, "pflags"},
1248         {ev_float, "ping"},
1249         {ev_float, "pitch_speed"},
1250         {ev_float, "pmodel"},
1251         {ev_float, "renderamt"}, // HalfLife support
1252         {ev_float, "rendermode"}, // HalfLife support
1253         {ev_float, "scale"},
1254         {ev_float, "style"},
1255         {ev_float, "tag_index"},
1256         {ev_float, "viewzoom"},
1257         {ev_vector, "color"},
1258         {ev_vector, "colormod"},
1259         {ev_vector, "cursor_screen"},
1260         {ev_vector, "cursor_trace_endpos"},
1261         {ev_vector, "cursor_trace_start"},
1262         {ev_vector, "movement"},
1263         {ev_vector, "punchvector"},
1264         {ev_string, "playermodel"},
1265         {ev_string, "playerskin"}
1266 };
1267
1268 /*
1269 ===============
1270 PR_LoadProgs
1271 ===============
1272 */
1273 extern void PR_Cmd_Reset (void);
1274 void PR_LoadProgs (const char *progsname)
1275 {
1276         int i;
1277         dstatement_t *st;
1278         ddef_t *infielddefs;
1279         dfunction_t *dfunctions;
1280
1281         if (!progsname || !*progsname)
1282                 Host_Error("PR_LoadProgs: passed empty progsname");
1283
1284         PR_FreeAll();
1285
1286         progs = (dprograms_t *)FS_LoadFile (progsname, serverprogs_mempool, false);
1287         if (!progs)
1288                 Host_Error ("PR_LoadProgs: couldn't load %s", progsname);
1289
1290         Con_DPrintf("Programs occupy %iK.\n", fs_filesize/1024);
1291
1292         pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1293
1294 // byte swap the header
1295         for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1296                 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1297
1298         if (progs->version != PROG_VERSION)
1299                 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1300         if (progs->crc != PROGHEADER_CRC && progs->crc != 32401) // tenebrae crc also allowed
1301                 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1302
1303         //prog->functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1304         dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1305
1306         pr_strings = (char *)progs + progs->ofs_strings;
1307         pr_stringssize = 0;
1308         for (i = 0;i < progs->numstrings;i++)
1309         {
1310                 if (progs->ofs_strings + pr_stringssize >= fs_filesize)
1311                         Host_Error ("progs.dat strings go past end of file\n");
1312                 pr_stringssize += strlen (pr_strings + pr_stringssize) + 1;
1313         }
1314         pr_numknownstrings = 0;
1315         pr_maxknownstrings = 0;
1316         pr_knownstrings = NULL;
1317
1318         pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1319
1320         // we need to expand the fielddefs list to include all the engine fields,
1321         // so allocate a new place for it
1322         infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1323         pr_fielddefs = PR_Alloc((progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1324         prog->functions = PR_Alloc(sizeof(mfunction_t) * progs->numfunctions);
1325
1326         pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1327
1328         // moved edict_size calculation down below field adding code
1329
1330         pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1331         pr_globals = (float *)pr_global_struct;
1332
1333 // byte swap the lumps
1334         for (i=0 ; i<progs->numstatements ; i++)
1335         {
1336                 pr_statements[i].op = LittleShort(pr_statements[i].op);
1337                 pr_statements[i].a = LittleShort(pr_statements[i].a);
1338                 pr_statements[i].b = LittleShort(pr_statements[i].b);
1339                 pr_statements[i].c = LittleShort(pr_statements[i].c);
1340         }
1341
1342         for (i = 0;i < progs->numfunctions;i++)
1343         {
1344                 prog->functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1345                 prog->functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1346                 prog->functions[i].s_name = LittleLong (dfunctions[i].s_name);
1347                 prog->functions[i].s_file = LittleLong (dfunctions[i].s_file);
1348                 prog->functions[i].numparms = LittleLong (dfunctions[i].numparms);
1349                 prog->functions[i].locals = LittleLong (dfunctions[i].locals);
1350                 memcpy(prog->functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1351         }
1352
1353         for (i=0 ; i<progs->numglobaldefs ; i++)
1354         {
1355                 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1356                 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1357                 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1358         }
1359
1360         // copy the progs fields to the new fields list
1361         for (i = 0;i < progs->numfielddefs;i++)
1362         {
1363                 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1364                 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1365                         Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1366                 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1367                 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1368         }
1369
1370         // append the darkplaces fields
1371         for (i = 0;i < (int) DPFIELDS;i++)
1372         {
1373                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1374                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1375                 pr_fielddefs[progs->numfielddefs].s_name = PRVM_SetEngineString(dpfields[i].string);
1376                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1377                         progs->entityfields += 3;
1378                 else
1379                         progs->entityfields++;
1380                 progs->numfielddefs++;
1381         }
1382
1383         for (i=0 ; i<progs->numglobals ; i++)
1384                 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1385
1386         // moved edict_size calculation down here, below field adding code
1387         // LordHavoc: this no longer includes the prvm_edict_t header
1388         prog->edict_size = progs->entityfields * 4;
1389         pr_edictareasize = prog->edict_size * MAX_EDICTS;
1390
1391         // LordHavoc: bounds check anything static
1392         for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1393         {
1394                 switch (st->op)
1395                 {
1396                 case OP_IF:
1397                 case OP_IFNOT:
1398                         if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1399                                 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1400                         break;
1401                 case OP_GOTO:
1402                         if (st->a + i < 0 || st->a + i >= progs->numstatements)
1403                                 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1404                         break;
1405                 // global global global
1406                 case OP_ADD_F:
1407                 case OP_ADD_V:
1408                 case OP_SUB_F:
1409                 case OP_SUB_V:
1410                 case OP_MUL_F:
1411                 case OP_MUL_V:
1412                 case OP_MUL_FV:
1413                 case OP_MUL_VF:
1414                 case OP_DIV_F:
1415                 case OP_BITAND:
1416                 case OP_BITOR:
1417                 case OP_GE:
1418                 case OP_LE:
1419                 case OP_GT:
1420                 case OP_LT:
1421                 case OP_AND:
1422                 case OP_OR:
1423                 case OP_EQ_F:
1424                 case OP_EQ_V:
1425                 case OP_EQ_S:
1426                 case OP_EQ_E:
1427                 case OP_EQ_FNC:
1428                 case OP_NE_F:
1429                 case OP_NE_V:
1430                 case OP_NE_S:
1431                 case OP_NE_E:
1432                 case OP_NE_FNC:
1433                 case OP_ADDRESS:
1434                 case OP_LOAD_F:
1435                 case OP_LOAD_FLD:
1436                 case OP_LOAD_ENT:
1437                 case OP_LOAD_S:
1438                 case OP_LOAD_FNC:
1439                 case OP_LOAD_V:
1440                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1441                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1442                         break;
1443                 // global none global
1444                 case OP_NOT_F:
1445                 case OP_NOT_V:
1446                 case OP_NOT_S:
1447                 case OP_NOT_FNC:
1448                 case OP_NOT_ENT:
1449                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1450                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1451                         break;
1452                 // 2 globals
1453                 case OP_STOREP_F:
1454                 case OP_STOREP_ENT:
1455                 case OP_STOREP_FLD:
1456                 case OP_STOREP_S:
1457                 case OP_STOREP_FNC:
1458                 case OP_STORE_F:
1459                 case OP_STORE_ENT:
1460                 case OP_STORE_FLD:
1461                 case OP_STORE_S:
1462                 case OP_STORE_FNC:
1463                 case OP_STATE:
1464                 case OP_STOREP_V:
1465                 case OP_STORE_V:
1466                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1467                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1468                         break;
1469                 // 1 global
1470                 case OP_CALL0:
1471                 case OP_CALL1:
1472                 case OP_CALL2:
1473                 case OP_CALL3:
1474                 case OP_CALL4:
1475                 case OP_CALL5:
1476                 case OP_CALL6:
1477                 case OP_CALL7:
1478                 case OP_CALL8:
1479                 case OP_DONE:
1480                 case OP_RETURN:
1481                         if ((unsigned short) st->a >= progs->numglobals)
1482                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1483                         break;
1484                 default:
1485                         Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1486                         break;
1487                 }
1488         }
1489
1490         FindEdictFieldOffsets(); // LordHavoc: update field offset list
1491         PR_Execute_ProgsLoaded();
1492         PR_Cmd_Reset();
1493 }
1494
1495
1496 void PR_Fields_f (void)
1497 {
1498         int i, j, ednum, used, usedamount;
1499         int *counts;
1500         const char *name;
1501         char tempstring[5000], tempstring2[260];
1502         prvm_edict_t *ed;
1503         ddef_t *d;
1504         int *v;
1505         if (!sv.active)
1506         {
1507                 Con_Print("no progs loaded\n");
1508                 return;
1509         }
1510         counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1511         for (ednum = 0;ednum < prog->max_edicts;ednum++)
1512         {
1513                 ed = PRVM_EDICT_NUM(ednum);
1514                 if (ed->priv.server->free)
1515                         continue;
1516                 for (i = 1;i < progs->numfielddefs;i++)
1517                 {
1518                         d = &pr_fielddefs[i];
1519                         name = PRVM_GetString(d->s_name);
1520                         if (name[strlen(name)-2] == '_')
1521                                 continue;       // skip _x, _y, _z vars
1522                         v = (int *)((char *)ed->v + d->ofs*4);
1523                         // if the value is still all 0, skip the field
1524                         for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1525                         {
1526                                 if (v[j])
1527                                 {
1528                                         counts[i]++;
1529                                         break;
1530                                 }
1531                         }
1532                 }
1533         }
1534         used = 0;
1535         usedamount = 0;
1536         tempstring[0] = 0;
1537         for (i = 0;i < progs->numfielddefs;i++)
1538         {
1539                 d = &pr_fielddefs[i];
1540                 name = PRVM_GetString(d->s_name);
1541                 if (name[strlen(name)-2] == '_')
1542                         continue;       // skip _x, _y, _z vars
1543                 switch(d->type & ~DEF_SAVEGLOBAL)
1544                 {
1545                 case ev_string:
1546                         strlcat (tempstring, "string   ", sizeof (tempstring));
1547                         break;
1548                 case ev_entity:
1549                         strlcat (tempstring, "entity   ", sizeof (tempstring));
1550                         break;
1551                 case ev_function:
1552                         strlcat (tempstring, "function ", sizeof (tempstring));
1553                         break;
1554                 case ev_field:
1555                         strlcat (tempstring, "field    ", sizeof (tempstring));
1556                         break;
1557                 case ev_void:
1558                         strlcat (tempstring, "void     ", sizeof (tempstring));
1559                         break;
1560                 case ev_float:
1561                         strlcat (tempstring, "float    ", sizeof (tempstring));
1562                         break;
1563                 case ev_vector:
1564                         strlcat (tempstring, "vector   ", sizeof (tempstring));
1565                         break;
1566                 case ev_pointer:
1567                         strlcat (tempstring, "pointer  ", sizeof (tempstring));
1568                         break;
1569                 default:
1570                         dpsnprintf (tempstring2, sizeof (tempstring2), "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1571                         strlcat (tempstring, tempstring2, sizeof (tempstring));
1572                         break;
1573                 }
1574                 if (strlen(name) > 256)
1575                 {
1576                         memcpy(tempstring2, name, 256);
1577                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1578                         tempstring2[259] = 0;
1579                         name = tempstring2;
1580                 }
1581                 strcat (tempstring, name);
1582                 for (j = strlen(name);j < 25;j++)
1583                         strcat(tempstring, " ");
1584                 dpsnprintf (tempstring2, sizeof (tempstring2), "%5d", counts[i]);
1585                 strlcat (tempstring, tempstring2, sizeof (tempstring));
1586                 strlcat (tempstring, "\n", sizeof (tempstring));
1587                 if (strlen(tempstring) >= 4096)
1588                 {
1589                         Con_Print(tempstring);
1590                         tempstring[0] = 0;
1591                 }
1592                 if (counts[i])
1593                 {
1594                         used++;
1595                         usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1596                 }
1597         }
1598         Mem_Free(counts);
1599         Con_Printf("%i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts allocated, %i bytes total spent on edict fields (%i needed)\n", progs->entityfields, used, progs->entityfields * 4, usedamount * 4, prog->max_edicts, progs->entityfields * 4 * prog->max_edicts, usedamount * 4 * prog->max_edicts);
1600 }
1601
1602 void PR_Globals_f (void)
1603 {
1604         int i;
1605         if (!sv.active)
1606         {
1607                 Con_Print("no progs loaded\n");
1608                 return;
1609         }
1610         for (i = 0;i < progs->numglobaldefs;i++)
1611                 Con_Printf("%s\n", PRVM_GetString(pr_globaldefs[i].s_name));
1612         Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1613 }
1614
1615 /*
1616 ===============
1617 PR_Init
1618 ===============
1619 */
1620 extern void PR_Cmd_Init(void);
1621 void PR_Init (void)
1622 {
1623         Cmd_AddCommand ("edict", ED_PrintEdict_f);
1624         Cmd_AddCommand ("edicts", ED_PrintEdicts);
1625         Cmd_AddCommand ("edictcount", ED_Count);
1626         Cmd_AddCommand ("edictset", ED_EdictSet_f);
1627         Cmd_AddCommand ("profile", PR_Profile_f);
1628         Cmd_AddCommand ("pr_fields", PR_Fields_f);
1629         Cmd_AddCommand ("pr_globals", PR_Globals_f);
1630         Cvar_RegisterVariable (&pr_checkextension);
1631         Cvar_RegisterVariable (&nomonsters);
1632         Cvar_RegisterVariable (&gamecfg);
1633         Cvar_RegisterVariable (&scratch1);
1634         Cvar_RegisterVariable (&scratch2);
1635         Cvar_RegisterVariable (&scratch3);
1636         Cvar_RegisterVariable (&scratch4);
1637         Cvar_RegisterVariable (&savedgamecfg);
1638         Cvar_RegisterVariable (&saved1);
1639         Cvar_RegisterVariable (&saved2);
1640         Cvar_RegisterVariable (&saved3);
1641         Cvar_RegisterVariable (&saved4);
1642         // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1643         Cvar_RegisterVariable (&decors);
1644         // LordHavoc: Nehahra uses these to pass data around cutscene demos
1645         if (gamemode == GAME_NEHAHRA)
1646         {
1647                 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1648                 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1649                 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1650                 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1651                 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1652                 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1653                 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1654                 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1655                 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1656                 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1657         }
1658         Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1659         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1660         Cvar_RegisterVariable (&pr_boundscheck);
1661         Cvar_RegisterVariable (&pr_traceqc);
1662
1663         serverprogs_mempool = Mem_AllocPool("server progs", 0, NULL);
1664
1665         PR_Cmd_Init();
1666 }
1667
1668 /*
1669 ===============
1670 PR_Shutdown
1671 ===============
1672 */
1673 extern void PR_Cmd_Shutdown(void);
1674 void PR_Shutdown (void)
1675 {
1676         PR_Cmd_Shutdown();
1677
1678         Mem_FreePool(&serverprogs_mempool);
1679 }
1680
1681 void *_PR_Alloc(size_t buffersize, const char *filename, int fileline)
1682 {
1683         return _Mem_Alloc(serverprogs_mempool, buffersize, filename, fileline);
1684 }
1685
1686 void _PR_Free(void *buffer, const char *filename, int fileline)
1687 {
1688         _Mem_Free(buffer, filename, fileline);
1689 }
1690
1691 void _PR_FreeAll(const char *filename, int fileline)
1692 {
1693         progs = NULL;
1694         pr_fielddefs = NULL;
1695         prog->functions = NULL;
1696         _Mem_EmptyPool(serverprogs_mempool, filename, fileline);
1697 }
1698
1699 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
1700 prvm_edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1701 {
1702         Host_Error ("PRVM_EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1703         return NULL;
1704 }
1705
1706 /*
1707 int NUM_FOR_EDICT_ERROR(prvm_edict_t *e)
1708 {
1709         Host_Error ("PRVM_NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, prog->edicts, e - prog->edicts);
1710         return 0;
1711 }
1712
1713 int PRVM_NUM_FOR_EDICT(prvm_edict_t *e)
1714 {
1715         int n;
1716         n = e - prog->edicts;
1717         if ((unsigned int)n >= MAX_EDICTS)
1718                 Host_Error ("PRVM_NUM_FOR_EDICT: bad pointer");
1719         return n;
1720 }
1721
1722 //int NoCrash_NUM_FOR_EDICT(prvm_edict_t *e)
1723 //{
1724 //      return e - prog->edicts;
1725 //}
1726
1727 //#define       PRVM_EDICT_TO_PROG(e) ((qbyte *)(((prvm_edict_t *)e)->v) - (qbyte *)(prog->edictsfields))
1728 //#define PRVM_PROG_TO_EDICT(e) (prog->edicts + ((e) / (progs->entityfields * 4)))
1729 int PRVM_EDICT_TO_PROG(prvm_edict_t *e)
1730 {
1731         int n;
1732         n = e - prog->edicts;
1733         if ((unsigned int)n >= (unsigned int)prog->max_edicts)
1734                 Host_Error("PRVM_EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, prog->edicts);
1735         return n;// EXPERIMENTAL
1736         //return (qbyte *)e->v - (qbyte *)prog->edictsfields;
1737 }
1738 prvm_edict_t *PRVM_PROG_TO_EDICT(int n)
1739 {
1740         if ((unsigned int)n >= (unsigned int)prog->max_edicts)
1741                 Host_Error("PRVM_PROG_TO_EDICT: invalid edict number %i\n", n);
1742         return prog->edicts + n; // EXPERIMENTAL
1743         //return prog->edicts + ((n) / (progs->entityfields * 4));
1744 }
1745 */
1746
1747 const char *PRVM_GetString(int num)
1748 {
1749         if (num >= 0 && num < pr_stringssize)
1750                 return pr_strings + num;
1751         else if (num < 0 && num >= -pr_numknownstrings)
1752         {
1753                 num = -1 - num;
1754                 if (!pr_knownstrings[num])
1755                         Host_Error("PRVM_GetString: attempt to get string that is already freed\n");
1756                 return pr_knownstrings[num];
1757         }
1758         else
1759         {
1760                 Host_Error("PRVM_GetString: invalid string offset %i\n", num);
1761                 return "";
1762         }
1763 }
1764
1765 int PR_SetQCString(const char *s)
1766 {
1767         int i;
1768         if (!s)
1769                 return 0;
1770         if (s >= pr_strings && s <= pr_strings + pr_stringssize)
1771                 return s - pr_strings;
1772         for (i = 0;i < pr_numknownstrings;i++)
1773                 if (pr_knownstrings[i] == s)
1774                         return -1 - i;
1775         Host_Error("PR_SetQCString: unknown string\n");
1776         return -1 - i;
1777 }
1778
1779 int PRVM_SetEngineString(const char *s)
1780 {
1781         int i;
1782         if (!s)
1783                 return 0;
1784         if (s >= pr_strings && s <= pr_strings + pr_stringssize)
1785                 Host_Error("PRVM_SetEngineString: s in pr_strings area\n");
1786         for (i = 0;i < pr_numknownstrings;i++)
1787                 if (pr_knownstrings[i] == s)
1788                         return -1 - i;
1789         // new unknown engine string
1790         if (developer.integer >= 3)
1791                 Con_Printf("new engine string %p\n", s);
1792         for (i = 0;i < pr_numknownstrings;i++)
1793                 if (!pr_knownstrings[i])
1794                         break;
1795         if (i >= pr_numknownstrings)
1796         {
1797                 if (i >= pr_maxknownstrings)
1798                 {
1799                         const char **oldstrings = pr_knownstrings;
1800                         pr_maxknownstrings += 128;
1801                         pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
1802                         if (pr_numknownstrings)
1803                                 memcpy((char **)pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
1804                 }
1805                 pr_numknownstrings++;
1806         }
1807         pr_knownstrings[i] = s;
1808         return -1 - i;
1809 }
1810
1811 char *PR_AllocString(int bufferlength)
1812 {
1813         int i;
1814         if (!bufferlength)
1815                 return 0;
1816         for (i = 0;i < pr_numknownstrings;i++)
1817                 if (!pr_knownstrings[i])
1818                         break;
1819         if (i >= pr_numknownstrings)
1820         {
1821                 if (i >= pr_maxknownstrings)
1822                 {
1823                         const char **oldstrings = pr_knownstrings;
1824                         pr_maxknownstrings += 128;
1825                         pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
1826                         if (pr_numknownstrings)
1827                                 memcpy((char **)pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
1828                 }
1829                 pr_numknownstrings++;
1830         }
1831         return (char *)(pr_knownstrings[i] = PR_Alloc(bufferlength));
1832 }
1833
1834 void PR_FreeString(char *s)
1835 {
1836         int i;
1837         if (!s)
1838                 Host_Error("PR_FreeString: attempt to free a NULL string\n");
1839         if (s >= pr_strings && s <= pr_strings + pr_stringssize)
1840                 Host_Error("PR_FreeString: attempt to free a constant string\n");
1841         for (i = 0;i < pr_numknownstrings;i++)
1842                 if (pr_knownstrings[i] == s)
1843                         break;
1844         if (i == pr_numknownstrings)
1845                 Host_Error("PR_FreeString: attempt to free a non-existent or already freed string\n");
1846         PR_Free((char *)pr_knownstrings[i]);
1847         pr_knownstrings[i] = NULL;
1848 }
1849