home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / common / bspfile.c next >
Encoding:
C/C++ Source or Header  |  1997-11-20  |  16.8 KB  |  769 lines

  1.  
  2. #include "cmdlib.h"
  3. #include "mathlib.h"
  4. #include "bspfile.h"
  5. #include "scriplib.h"
  6.  
  7. void GetLeafNums (void);
  8.  
  9. //=============================================================================
  10.  
  11. int            nummodels;
  12. dmodel_t    dmodels[MAX_MAP_MODELS];
  13.  
  14. int            visdatasize;
  15. byte        dvisdata[MAX_MAP_VISIBILITY];
  16. dvis_t        *dvis = (dvis_t *)dvisdata;
  17.  
  18. int            lightdatasize;
  19. byte        dlightdata[MAX_MAP_LIGHTING];
  20.  
  21. int            entdatasize;
  22. char        dentdata[MAX_MAP_ENTSTRING];
  23.  
  24. int            numleafs;
  25. dleaf_t        dleafs[MAX_MAP_LEAFS];
  26.  
  27. int            numplanes;
  28. dplane_t    dplanes[MAX_MAP_PLANES];
  29.  
  30. int            numvertexes;
  31. dvertex_t    dvertexes[MAX_MAP_VERTS];
  32.  
  33. int            numnodes;
  34. dnode_t        dnodes[MAX_MAP_NODES];
  35.  
  36. int            numtexinfo;
  37. texinfo_t    texinfo[MAX_MAP_TEXINFO];
  38.  
  39. int            numfaces;
  40. dface_t        dfaces[MAX_MAP_FACES];
  41.  
  42. int            numedges;
  43. dedge_t        dedges[MAX_MAP_EDGES];
  44.  
  45. int            numleaffaces;
  46. unsigned short        dleaffaces[MAX_MAP_LEAFFACES];
  47.  
  48. int            numleafbrushes;
  49. unsigned short        dleafbrushes[MAX_MAP_LEAFBRUSHES];
  50.  
  51. int            numsurfedges;
  52. int            dsurfedges[MAX_MAP_SURFEDGES];
  53.  
  54. int            numbrushes;
  55. dbrush_t    dbrushes[MAX_MAP_BRUSHES];
  56.  
  57. int            numbrushsides;
  58. dbrushside_t    dbrushsides[MAX_MAP_BRUSHSIDES];
  59.  
  60. int            numareas;
  61. darea_t        dareas[MAX_MAP_AREAS];
  62.  
  63. int            numareaportals;
  64. dareaportal_t    dareaportals[MAX_MAP_AREAPORTALS];
  65.  
  66. byte        dpop[256];
  67.  
  68. /*
  69. ===============
  70. CompressVis
  71.  
  72. ===============
  73. */
  74. int CompressVis (byte *vis, byte *dest)
  75. {
  76.     int        j;
  77.     int        rep;
  78.     int        visrow;
  79.     byte    *dest_p;
  80.     
  81.     dest_p = dest;
  82. //    visrow = (r_numvisleafs + 7)>>3;
  83.     visrow = (dvis->numclusters + 7)>>3;
  84.     
  85.     for (j=0 ; j<visrow ; j++)
  86.     {
  87.         *dest_p++ = vis[j];
  88.         if (vis[j])
  89.             continue;
  90.  
  91.         rep = 1;
  92.         for ( j++; j<visrow ; j++)
  93.             if (vis[j] || rep == 255)
  94.                 break;
  95.             else
  96.                 rep++;
  97.         *dest_p++ = rep;
  98.         j--;
  99.     }
  100.     
  101.     return dest_p - dest;
  102. }
  103.  
  104.  
  105. /*
  106. ===================
  107. DecompressVis
  108. ===================
  109. */
  110. void DecompressVis (byte *in, byte *decompressed)
  111. {
  112.     int        c;
  113.     byte    *out;
  114.     int        row;
  115.  
  116. //    row = (r_numvisleafs+7)>>3;    
  117.     row = (dvis->numclusters+7)>>3;    
  118.     out = decompressed;
  119.  
  120.     do
  121.     {
  122.         if (*in)
  123.         {
  124.             *out++ = *in++;
  125.             continue;
  126.         }
  127.     
  128.         c = in[1];
  129.         if (!c)
  130.             Error ("DecompressVis: 0 repeat");
  131.         in += 2;
  132.         while (c)
  133.         {
  134.             *out++ = 0;
  135.             c--;
  136.         }
  137.     } while (out - decompressed < row);
  138. }
  139.  
  140. //=============================================================================
  141.  
  142. /*
  143. =============
  144. SwapBSPFile
  145.  
  146. Byte swaps all data in a bsp file.
  147. =============
  148. */
  149. void SwapBSPFile (qboolean todisk)
  150. {
  151.     int                i, j;
  152.     dmodel_t        *d;
  153.  
  154.     
  155. // models    
  156.     for (i=0 ; i<nummodels ; i++)
  157.     {
  158.         d = &dmodels[i];
  159.  
  160.         d->firstface = LittleLong (d->firstface);
  161.         d->numfaces = LittleLong (d->numfaces);
  162.         d->headnode = LittleLong (d->headnode);
  163.         
  164.         for (j=0 ; j<3 ; j++)
  165.         {
  166.             d->mins[j] = LittleFloat(d->mins[j]);
  167.             d->maxs[j] = LittleFloat(d->maxs[j]);
  168.             d->origin[j] = LittleFloat(d->origin[j]);
  169.         }
  170.     }
  171.  
  172. //
  173. // vertexes
  174. //
  175.     for (i=0 ; i<numvertexes ; i++)
  176.     {
  177.         for (j=0 ; j<3 ; j++)
  178.             dvertexes[i].point[j] = LittleFloat (dvertexes[i].point[j]);
  179.     }
  180.         
  181. //
  182. // planes
  183. //    
  184.     for (i=0 ; i<numplanes ; i++)
  185.     {
  186.         for (j=0 ; j<3 ; j++)
  187.             dplanes[i].normal[j] = LittleFloat (dplanes[i].normal[j]);
  188.         dplanes[i].dist = LittleFloat (dplanes[i].dist);
  189.         dplanes[i].type = LittleLong (dplanes[i].type);
  190.     }
  191.     
  192. //
  193. // texinfos
  194. //    
  195.     for (i=0 ; i<numtexinfo ; i++)
  196.     {
  197.         for (j=0 ; j<8 ; j++)
  198.             texinfo[i].vecs[0][j] = LittleFloat (texinfo[i].vecs[0][j]);
  199.         texinfo[i].flags = LittleLong (texinfo[i].flags);
  200.         texinfo[i].value = LittleLong (texinfo[i].value);
  201.         texinfo[i].nexttexinfo = LittleLong (texinfo[i].nexttexinfo);
  202.     }
  203.     
  204. //
  205. // faces
  206. //
  207.     for (i=0 ; i<numfaces ; i++)
  208.     {
  209.         dfaces[i].texinfo = LittleShort (dfaces[i].texinfo);
  210.         dfaces[i].planenum = LittleShort (dfaces[i].planenum);
  211.         dfaces[i].side = LittleShort (dfaces[i].side);
  212.         dfaces[i].lightofs = LittleLong (dfaces[i].lightofs);
  213.         dfaces[i].firstedge = LittleLong (dfaces[i].firstedge);
  214.         dfaces[i].numedges = LittleShort (dfaces[i].numedges);
  215.     }
  216.  
  217. //
  218. // nodes
  219. //
  220.     for (i=0 ; i<numnodes ; i++)
  221.     {
  222.         dnodes[i].planenum = LittleLong (dnodes[i].planenum);
  223.         for (j=0 ; j<3 ; j++)
  224.         {
  225.             dnodes[i].mins[j] = LittleShort (dnodes[i].mins[j]);
  226.             dnodes[i].maxs[j] = LittleShort (dnodes[i].maxs[j]);
  227.         }
  228.         dnodes[i].children[0] = LittleLong (dnodes[i].children[0]);
  229.         dnodes[i].children[1] = LittleLong (dnodes[i].children[1]);
  230.         dnodes[i].firstface = LittleShort (dnodes[i].firstface);
  231.         dnodes[i].numfaces = LittleShort (dnodes[i].numfaces);
  232.     }
  233.  
  234. //
  235. // leafs
  236. //
  237.     for (i=0 ; i<numleafs ; i++)
  238.     {
  239.         dleafs[i].contents = LittleLong (dleafs[i].contents);
  240.         dleafs[i].cluster = LittleShort (dleafs[i].cluster);
  241.         dleafs[i].area = LittleShort (dleafs[i].area);
  242.         for (j=0 ; j<3 ; j++)
  243.         {
  244.             dleafs[i].mins[j] = LittleShort (dleafs[i].mins[j]);
  245.             dleafs[i].maxs[j] = LittleShort (dleafs[i].maxs[j]);
  246.         }
  247.  
  248.         dleafs[i].firstleafface = LittleShort (dleafs[i].firstleafface);
  249.         dleafs[i].numleaffaces = LittleShort (dleafs[i].numleaffaces);
  250.         dleafs[i].firstleafbrush = LittleShort (dleafs[i].firstleafbrush);
  251.         dleafs[i].numleafbrushes = LittleShort (dleafs[i].numleafbrushes);
  252.     }
  253.  
  254. //
  255. // leaffaces
  256. //
  257.     for (i=0 ; i<numleaffaces ; i++)
  258.         dleaffaces[i] = LittleShort (dleaffaces[i]);
  259.  
  260. //
  261. // leafbrushes
  262. //
  263.     for (i=0 ; i<numleafbrushes ; i++)
  264.         dleafbrushes[i] = LittleShort (dleafbrushes[i]);
  265.  
  266. //
  267. // surfedges
  268. //
  269.     for (i=0 ; i<numsurfedges ; i++)
  270.         dsurfedges[i] = LittleLong (dsurfedges[i]);
  271.  
  272. //
  273. // edges
  274. //
  275.     for (i=0 ; i<numedges ; i++)
  276.     {
  277.         dedges[i].v[0] = LittleShort (dedges[i].v[0]);
  278.         dedges[i].v[1] = LittleShort (dedges[i].v[1]);
  279.     }
  280.  
  281. //
  282. // brushes
  283. //
  284.     for (i=0 ; i<numbrushes ; i++)
  285.     {
  286.         dbrushes[i].firstside = LittleLong (dbrushes[i].firstside);
  287.         dbrushes[i].numsides = LittleLong (dbrushes[i].numsides);
  288.         dbrushes[i].contents = LittleLong (dbrushes[i].contents);
  289.     }
  290.  
  291. //
  292. // areas
  293. //
  294.     for (i=0 ; i<numareas ; i++)
  295.     {
  296.         dareas[i].numareaportals = LittleLong (dareas[i].numareaportals);
  297.         dareas[i].firstareaportal = LittleLong (dareas[i].firstareaportal);
  298.     }
  299.  
  300. //
  301. // areasportals
  302. //
  303.     for (i=0 ; i<numareaportals ; i++)
  304.     {
  305.         dareaportals[i].portalnum = LittleLong (dareaportals[i].portalnum);
  306.         dareaportals[i].otherarea = LittleLong (dareaportals[i].otherarea);
  307.     }
  308.  
  309. //
  310. // brushsides
  311. //
  312.     for (i=0 ; i<numbrushsides ; i++)
  313.     {
  314.         dbrushsides[i].planenum = LittleShort (dbrushsides[i].planenum);
  315.         dbrushsides[i].texinfo = LittleShort (dbrushsides[i].texinfo);
  316.     }
  317.  
  318. //
  319. // visibility
  320. //
  321.     if (todisk)
  322.         j = dvis->numclusters;
  323.     else
  324.         j = LittleLong(dvis->numclusters);
  325.     dvis->numclusters = LittleLong (dvis->numclusters);
  326.     for (i=0 ; i<j ; i++)
  327.     {
  328.         dvis->bitofs[i][0] = LittleLong (dvis->bitofs[i][0]);
  329.         dvis->bitofs[i][1] = LittleLong (dvis->bitofs[i][1]);
  330.     }
  331. }
  332.  
  333.  
  334. dheader_t    *header;
  335.  
  336. int CopyLump (int lump, void *dest, int size)
  337. {
  338.     int        length, ofs;
  339.  
  340.     length = header->lumps[lump].filelen;
  341.     ofs = header->lumps[lump].fileofs;
  342.     
  343.     if (length % size)
  344.         Error ("LoadBSPFile: odd lump size");
  345.     
  346.     memcpy (dest, (byte *)header + ofs, length);
  347.  
  348.     return length / size;
  349. }
  350.  
  351. /*
  352. =============
  353. LoadBSPFile
  354. =============
  355. */
  356. void    LoadBSPFile (char *filename)
  357. {
  358.     int            i;
  359.     
  360. //
  361. // load the file header
  362. //
  363.     LoadFile (filename, (void **)&header);
  364.  
  365. // swap the header
  366.     for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
  367.         ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
  368.  
  369.     if (header->ident != IDBSPHEADER)
  370.         Error ("%s is not a IBSP file", filename);
  371.     if (header->version != BSPVERSION)
  372.         Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
  373.  
  374.     nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t));
  375.     numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t));
  376.     numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t));
  377.     numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t));
  378.     numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t));
  379.     numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t));
  380.     numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t));
  381.     numleaffaces = CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0]));
  382.     numleafbrushes = CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]));
  383.     numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0]));
  384.     numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t));
  385.     numbrushes = CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t));
  386.     numbrushsides = CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t));
  387.     numareas = CopyLump (LUMP_AREAS, dareas, sizeof(darea_t));
  388.     numareaportals = CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t));
  389.  
  390.     visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1);
  391.     lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1);
  392.     entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1);
  393.  
  394.     CopyLump (LUMP_POP, dpop, 1);
  395.  
  396.     free (header);        // everything has been copied out
  397.         
  398. //
  399. // swap everything
  400. //    
  401.     SwapBSPFile (false);
  402. }
  403.  
  404.  
  405. /*
  406. =============
  407. LoadBSPFileTexinfo
  408.  
  409. Only loads the texinfo lump, so qdata can scan for textures
  410. =============
  411. */
  412. void    LoadBSPFileTexinfo (char *filename)
  413. {
  414.     int            i;
  415.     FILE        *f;
  416.     int        length, ofs;
  417.  
  418.     header = malloc(sizeof(dheader_t));
  419.  
  420.     f = fopen (filename, "rb");
  421.     fread (header, sizeof(dheader_t), 1, f);
  422.  
  423. // swap the header
  424.     for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
  425.         ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
  426.  
  427.     if (header->ident != IDBSPHEADER)
  428.         Error ("%s is not a IBSP file", filename);
  429.     if (header->version != BSPVERSION)
  430.         Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
  431.  
  432.  
  433.     length = header->lumps[LUMP_TEXINFO].filelen;
  434.     ofs = header->lumps[LUMP_TEXINFO].fileofs;
  435.  
  436.     fseek (f, ofs, SEEK_SET);
  437.     fread (texinfo, length, 1, f);
  438.     fclose (f);
  439.  
  440.     numtexinfo = length / sizeof(texinfo_t);
  441.  
  442.     free (header);        // everything has been copied out
  443.         
  444.     SwapBSPFile (false);
  445. }
  446.  
  447.  
  448. //============================================================================
  449.  
  450. FILE        *wadfile;
  451. dheader_t    outheader;
  452.  
  453. void AddLump (int lumpnum, void *data, int len)
  454. {
  455.     lump_t *lump;
  456.  
  457.     lump = &header->lumps[lumpnum];
  458.     
  459.     lump->fileofs = LittleLong( ftell(wadfile) );
  460.     lump->filelen = LittleLong(len);
  461.     SafeWrite (wadfile, data, (len+3)&~3);
  462. }
  463.  
  464. /*
  465. =============
  466. WriteBSPFile
  467.  
  468. Swaps the bsp file in place, so it should not be referenced again
  469. =============
  470. */
  471. void    WriteBSPFile (char *filename)
  472. {        
  473.     header = &outheader;
  474.     memset (header, 0, sizeof(dheader_t));
  475.     
  476.     SwapBSPFile (true);
  477.  
  478.     header->ident = LittleLong (IDBSPHEADER);
  479.     header->version = LittleLong (BSPVERSION);
  480.     
  481.     wadfile = SafeOpenWrite (filename);
  482.     SafeWrite (wadfile, header, sizeof(dheader_t));    // overwritten later
  483.  
  484.     AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t));
  485.     AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t));
  486.     AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t));
  487.     AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t));
  488.     AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t));
  489.     AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t));
  490.     AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t));
  491.     AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t));
  492.     AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0]));
  493.     AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]));
  494.     AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0]));
  495.     AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t));
  496.     AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t));
  497.     AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t));
  498.     AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t));
  499.  
  500.     AddLump (LUMP_LIGHTING, dlightdata, lightdatasize);
  501.     AddLump (LUMP_VISIBILITY, dvisdata, visdatasize);
  502.     AddLump (LUMP_ENTITIES, dentdata, entdatasize);
  503.     AddLump (LUMP_POP, dpop, sizeof(dpop));
  504.     
  505.     fseek (wadfile, 0, SEEK_SET);
  506.     SafeWrite (wadfile, header, sizeof(dheader_t));
  507.     fclose (wadfile);    
  508. }
  509.  
  510. //============================================================================
  511.  
  512. /*
  513. =============
  514. PrintBSPFileSizes
  515.  
  516. Dumps info about current file
  517. =============
  518. */
  519. void PrintBSPFileSizes (void)
  520. {
  521.     if (!num_entities)
  522.         ParseEntities ();
  523.  
  524.     printf ("%5i models       %7i\n"
  525.         ,nummodels, (int)(nummodels*sizeof(dmodel_t)));
  526.     printf ("%5i brushes      %7i\n"
  527.         ,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
  528.     printf ("%5i brushsides   %7i\n"
  529.         ,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
  530.     printf ("%5i planes       %7i\n"
  531.         ,numplanes, (int)(numplanes*sizeof(dplane_t)));
  532.     printf ("%5i texinfo      %7i\n"
  533.         ,numtexinfo, (int)(numtexinfo*sizeof(texinfo_t)));
  534.     printf ("%5i entdata      %7i\n", num_entities, entdatasize);
  535.  
  536.     printf ("\n");
  537.  
  538.     printf ("%5i vertexes     %7i\n"
  539.         ,numvertexes, (int)(numvertexes*sizeof(dvertex_t)));
  540.     printf ("%5i nodes        %7i\n"
  541.         ,numnodes, (int)(numnodes*sizeof(dnode_t)));
  542.     printf ("%5i faces        %7i\n"
  543.         ,numfaces, (int)(numfaces*sizeof(dface_t)));
  544.     printf ("%5i leafs        %7i\n"
  545.         ,numleafs, (int)(numleafs*sizeof(dleaf_t)));
  546.     printf ("%5i leaffaces    %7i\n"
  547.         ,numleaffaces, (int)(numleaffaces*sizeof(dleaffaces[0])));
  548.     printf ("%5i leafbrushes  %7i\n"
  549.         ,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
  550.     printf ("%5i surfedges    %7i\n"
  551.         ,numsurfedges, (int)(numsurfedges*sizeof(dsurfedges[0])));
  552.     printf ("%5i edges        %7i\n"
  553.         ,numedges, (int)(numedges*sizeof(dedge_t)));
  554.     printf ("      lightdata    %7i\n", lightdatasize);
  555.     printf ("      visdata      %7i\n", visdatasize);
  556. }
  557.  
  558.  
  559. //============================================
  560.  
  561. int            num_entities;
  562. entity_t    entities[MAX_MAP_ENTITIES];
  563.  
  564. void StripTrailing (char *e)
  565. {
  566.     char    *s;
  567.  
  568.     s = e + strlen(e)-1;
  569.     while (s >= e && *s <= 32)
  570.     {
  571.         *s = 0;
  572.         s--;
  573.     }
  574. }
  575.  
  576. /*
  577. =================
  578. ParseEpair
  579. =================
  580. */
  581. epair_t *ParseEpair (void)
  582. {
  583.     epair_t    *e;
  584.  
  585.     e = malloc (sizeof(epair_t));
  586.     memset (e, 0, sizeof(epair_t));
  587.     
  588.     if (strlen(token) >= MAX_KEY-1)
  589.         Error ("ParseEpar: token too long");
  590.     e->key = copystring(token);
  591.     GetToken (false);
  592.     if (strlen(token) >= MAX_VALUE-1)
  593.         Error ("ParseEpar: token too long");
  594.     e->value = copystring(token);
  595.  
  596.     // strip trailing spaces
  597.     StripTrailing (e->key);
  598.     StripTrailing (e->value);
  599.  
  600.     return e;
  601. }
  602.  
  603.  
  604. /*
  605. ================
  606. ParseEntity
  607. ================
  608. */
  609. qboolean    ParseEntity (void)
  610. {
  611.     epair_t        *e;
  612.     entity_t    *mapent;
  613.  
  614.     if (!GetToken (true))
  615.         return false;
  616.  
  617.     if (strcmp (token, "{") )
  618.         Error ("ParseEntity: { not found");
  619.     
  620.     if (num_entities == MAX_MAP_ENTITIES)
  621.         Error ("num_entities == MAX_MAP_ENTITIES");
  622.  
  623.     mapent = &entities[num_entities];
  624.     num_entities++;
  625.  
  626.     do
  627.     {
  628.         if (!GetToken (true))
  629.             Error ("ParseEntity: EOF without closing brace");
  630.         if (!strcmp (token, "}") )
  631.             break;
  632.         e = ParseEpair ();
  633.         e->next = mapent->epairs;
  634.         mapent->epairs = e;
  635.     } while (1);
  636.     
  637.     return true;
  638. }
  639.  
  640. /*
  641. ================
  642. ParseEntities
  643.  
  644. Parses the dentdata string into entities
  645. ================
  646. */
  647. void ParseEntities (void)
  648. {
  649.     num_entities = 0;
  650.     ParseFromMemory (dentdata, entdatasize);
  651.  
  652.     while (ParseEntity ())
  653.     {
  654.     }    
  655. }
  656.  
  657.  
  658. /*
  659. ================
  660. UnparseEntities
  661.  
  662. Generates the dentdata string from all the entities
  663. ================
  664. */
  665. void UnparseEntities (void)
  666. {
  667.     char    *buf, *end;
  668.     epair_t    *ep;
  669.     char    line[2048];
  670.     int        i;
  671.     char    key[1024], value[1024];
  672.  
  673.     buf = dentdata;
  674.     end = buf;
  675.     *end = 0;
  676.     
  677.     for (i=0 ; i<num_entities ; i++)
  678.     {
  679.         ep = entities[i].epairs;
  680.         if (!ep)
  681.             continue;    // ent got removed
  682.         
  683.         strcat (end,"{\n");
  684.         end += 2;
  685.                 
  686.         for (ep = entities[i].epairs ; ep ; ep=ep->next)
  687.         {
  688.             strcpy (key, ep->key);
  689.             StripTrailing (key);
  690.             strcpy (value, ep->value);
  691.             StripTrailing (value);
  692.                 
  693.             sprintf (line, "\"%s\" \"%s\"\n", key, value);
  694.             strcat (end, line);
  695.             end += strlen(line);
  696.         }
  697.         strcat (end,"}\n");
  698.         end += 2;
  699.  
  700.         if (end > buf + MAX_MAP_ENTSTRING)
  701.             Error ("Entity text too long");
  702.     }
  703.     entdatasize = end - buf + 1;
  704. }
  705.  
  706. void PrintEntity (entity_t *ent)
  707. {
  708.     epair_t    *ep;
  709.     
  710.     printf ("------- entity %p -------\n", ent);
  711.     for (ep=ent->epairs ; ep ; ep=ep->next)
  712.     {
  713.         printf ("%s = %s\n", ep->key, ep->value);
  714.     }
  715.  
  716. }
  717.  
  718. void     SetKeyValue (entity_t *ent, char *key, char *value)
  719. {
  720.     epair_t    *ep;
  721.     
  722.     for (ep=ent->epairs ; ep ; ep=ep->next)
  723.         if (!strcmp (ep->key, key) )
  724.         {
  725.             free (ep->value);
  726.             ep->value = copystring(value);
  727.             return;
  728.         }
  729.     ep = malloc (sizeof(*ep));
  730.     ep->next = ent->epairs;
  731.     ent->epairs = ep;
  732.     ep->key = copystring(key);
  733.     ep->value = copystring(value);
  734. }
  735.  
  736. char     *ValueForKey (entity_t *ent, char *key)
  737. {
  738.     epair_t    *ep;
  739.     
  740.     for (ep=ent->epairs ; ep ; ep=ep->next)
  741.         if (!strcmp (ep->key, key) )
  742.             return ep->value;
  743.     return "";
  744. }
  745.  
  746. vec_t    FloatForKey (entity_t *ent, char *key)
  747. {
  748.     char    *k;
  749.     
  750.     k = ValueForKey (ent, key);
  751.     return atof(k);
  752. }
  753.  
  754. void     GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
  755. {
  756.     char    *k;
  757.     double    v1, v2, v3;
  758.  
  759.     k = ValueForKey (ent, key);
  760. // scanf into doubles, then assign, so it is vec_t size independent
  761.     v1 = v2 = v3 = 0;
  762.     sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
  763.     vec[0] = v1;
  764.     vec[1] = v2;
  765.     vec[2] = v3;
  766. }
  767.  
  768.  
  769.