]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/eclass_def.cpp
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / radiant / eclass_def.cpp
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 #include "cmdlib.h"\r
23 \r
24 #include "synapse.h"\r
25 #define USE_QERTABLE_DEFINE\r
26 #include "qerplugin.h"\r
27 #define USE_ECLASSMANAGER_DEFINE\r
28 #include "ieclass.h"\r
29 #define USE_SCRIPLIBTABLE_DEFINE\r
30 #include "iscriplib.h"\r
31 \r
32 #define __VFSTABLENAME g_FileSystemTable_def\r
33 #define USE_VFSTABLE_DEFINE\r
34 #include "ifilesystem.h"\r
35 \r
36 \r
37 #include "eclass_def.h"\r
38 \r
39 /*! \file eclass_def.cpp\r
40     \brief .def entity description format\r
41     implements parsing for .def entity format\r
42     this is statically linked into the radiant core as we always need it, but really considered\r
43     as an idependant module by the rest of the core. "ECLASS_MAJOR" "def"\r
44 */\r
45 \r
46 _QERScripLibTable g_ScripLibTable;\r
47 _EClassManagerTable g_EClassManagerTable;\r
48 _QERFuncTable_1 g_FuncTable;\r
49 _QERFileSystemTable g_FileSystemTable_def;\r
50 \r
51 CSynapseBuiltinClientDef eclass_def;\r
52 \r
53 // forward declare, I'm cheap\r
54 void Eclass_ScanFile (char *filename);\r
55 \r
56 const char* EClass_GetExtension()\r
57 {\r
58   return "def";\r
59 }\r
60 \r
61 void CSynapseBuiltinClientDef::EnumerateInterfaces(CSynapseServer *server)\r
62 {\r
63   AddAPI(SCRIPLIB_MAJOR, NULL, sizeof(g_ScripLibTable), SYN_REQUIRE, &g_ScripLibTable);\r
64   AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable);\r
65   AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(g_EClassManagerTable), SYN_REQUIRE, &g_EClassManagerTable);\r
66   // hardcode the minor for now, we can still add it to the synapse.config at some point\r
67   AddAPI(VFS_MAJOR, "pk3", sizeof(g_FileSystemTable_def), SYN_REQUIRE, &g_FileSystemTable_def);\r
68   \r
69   AddAPI(ECLASS_MAJOR, "def", sizeof(_EClassTable));\r
70 }\r
71 \r
72 bool CSynapseBuiltinClientDef::RequestAPI(APIDescriptor_t *pAPI)\r
73 {\r
74   if (!strcmp(pAPI->major_name, ECLASS_MAJOR))\r
75   {\r
76     _EClassTable* pTable= static_cast<_EClassTable*>(pAPI->mpTable);\r
77     pTable->m_pfnScanFile = &Eclass_ScanFile;\r
78     pTable->m_pfnGetExtension = &EClass_GetExtension;\r
79     \r
80     return true;    \r
81   }\r
82   \r
83   Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());\r
84   return false;\r
85 }\r
86 \r
87 #include "version.h"\r
88 \r
89 const char* CSynapseBuiltinClientDef::GetInfo()\r
90 {\r
91   return "Builtin .def module built " __DATE__ " " RADIANT_VERSION;\r
92 }\r
93 \r
94 // ------------------------------------------------------------------------------------------------\r
95 \r
96 qboolean eclass_found;\r
97 char *debugname;\r
98 \r
99 void setSpecialLoad(eclass_t *e, const char* pWhat, char*& p)\r
100 {\r
101   // Hydra: removed some amazingly bad cstring usage, whoever wrote that\r
102   // needs to be taken out and shot.\r
103 \r
104   char *pText = NULL;\r
105   char *where = NULL;\r
106 \r
107   p = NULL; // incase we don't find what we're looking for.\r
108   where = strstr(e->comments,pWhat);\r
109   if (!where)\r
110     return;\r
111 \r
112   pText = where + strlen(pWhat);\r
113   if (*pText == '\"')\r
114     pText++;\r
115 \r
116   where = strchr(pText,'\"');\r
117   if (where)\r
118   {\r
119     int len = (where-pText);\r
120     p = new char[len + 1];\r
121     strncpy(p,pText,len);\r
122     p[len]=0; // just to make sure, as most implementations of strncpy don't null terminate\r
123   }\r
124   else\r
125     p = strdup(pText);\r
126 }\r
127 \r
128 eclass_t *Eclass_InitFromText (char *text)\r
129 {\r
130         char    *t;\r
131         int             len;\r
132         int             r, i;\r
133         char    parms[256], *p;\r
134         eclass_t        *e;\r
135         char    color[128];\r
136 \r
137         e = (eclass_t*)malloc(sizeof(*e));\r
138         memset (e, 0, sizeof(*e));\r
139         \r
140         text += strlen("/*QUAKED ");\r
141 \r
142   // grab the name\r
143         text = COM_Parse (text);\r
144         e->name = (char*)malloc (strlen(Get_COM_Token())+1);\r
145         strcpy (e->name, Get_COM_Token());\r
146         debugname = e->name;\r
147 \r
148   // grab the color, reformat as texture name\r
149   r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]);\r
150   if (r != 3) {\r
151                 return e;\r
152   }\r
153         sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]);\r
154         //strcpy (e->texdef.name, color);\r
155         e->texdef.SetName(color);\r
156 \r
157         while (*text != ')')\r
158   {\r
159     if (!*text) {\r
160                         return e;\r
161     }\r
162                 text++;\r
163         }\r
164         text++;\r
165         \r
166   // get the size       \r
167         text = COM_Parse (text);\r
168         if (Get_COM_Token()[0] == '(')\r
169         {       // parse the size as two vectors\r
170                 e->fixedsize = true;\r
171                 r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2],\r
172                         &e->maxs[0], &e->maxs[1], &e->maxs[2]);\r
173     if (r != 6) {\r
174                         return e;\r
175     }\r
176 \r
177                 for (i=0 ; i<2 ; i++)\r
178                 {\r
179                         while (*text != ')')\r
180                         {\r
181         if (!*text) {\r
182                                         return e;\r
183         }\r
184                                 text++;\r
185                         }\r
186                         text++;\r
187                 }\r
188         }\r
189         \r
190   // get the flags\r
191         \r
192   // copy to the first /n\r
193         p = parms;\r
194         while (*text && *text != '\n')\r
195                 *p++ = *text++;\r
196         *p = 0;\r
197         text++;\r
198         \r
199   // any remaining words are parm flags\r
200         p = parms;\r
201         for (i=0 ; i<MAX_FLAGS ; i++)\r
202         {\r
203                 p = COM_Parse (p);\r
204                 if (!p)\r
205                         break;\r
206                 strcpy (e->flagnames[i], Get_COM_Token());\r
207         } \r
208 \r
209   // find the length until close comment\r
210         for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++)\r
211         ;\r
212         \r
213   // copy the comment block out\r
214         len = t-text;\r
215         e->comments = (char*)malloc (len+1);\r
216         memcpy (e->comments, text, len);\r
217 #ifdef _WIN32\r
218   // the win32 Gtk widgets are expecting text stuff to be in unix format (that is CR only instead of DOS's CR/LF)\r
219   // we convert on the fly by replacing the LF with a ' ' (yeah I'm cheap)\r
220         for (i=0 ; i<len ; i++)\r
221                 if (text[i] == '\r')\r
222                         e->comments[i] = ' ';\r
223                 else\r
224                         e->comments[i] = text[i];\r
225 #endif\r
226   e->comments[len] = 0;\r
227         \r
228   setSpecialLoad(e, "model=", e->modelpath);\r
229   setSpecialLoad(e, "skin=", e->skinpath);\r
230   char *pFrame = NULL;\r
231   setSpecialLoad(e, "frame=", pFrame);\r
232   if (pFrame != NULL)\r
233   {\r
234     e->nFrame = atoi(pFrame);\r
235     delete pFrame; //Hydra - Fixed memory leak!\r
236   }\r
237 \r
238   if(!e->skinpath)\r
239           setSpecialLoad(e, "texture=", e->skinpath);\r
240 \r
241   // setup show flags\r
242   e->nShowFlags = 0;\r
243   if (strcmpi(e->name, "light") == 0 || strcmpi(e->name, "dlight") == 0 || strcmpi(e->name, "lightjunior") == 0)\r
244   {\r
245     e->nShowFlags |= ECLASS_LIGHT;\r
246   }\r
247 \r
248   if (  (strnicmp(e->name, "info_player", strlen("info_player")) == 0)\r
249       ||(strnicmp(e->name, "path_corner", strlen("path_corner")) == 0) \r
250       ||(strnicmp(e->name, "team_ctf", strlen("team_ctf")) == 0) \r
251       ||(strnicmp(e->name, "misc_teleporter_dest", strlen("misc_teleporter_dest")) == 0) \r
252           )\r
253   {\r
254     e->nShowFlags |= ECLASS_ANGLE;\r
255   }\r
256   if (strcmpi(e->name, "path") == 0)\r
257   {\r
258     e->nShowFlags |= ECLASS_PATH;\r
259   }\r
260   if (strcmpi(e->name, "misc_model") == 0)\r
261   {\r
262     e->nShowFlags |= ECLASS_MISCMODEL;\r
263   }\r
264 \r
265 \r
266   return e;\r
267 }\r
268 \r
269 void Eclass_ScanFile (char *filename)\r
270 {\r
271         int             size;\r
272         char    *data;\r
273         eclass_t        *e;\r
274         int             i;\r
275         char    temp[1024];\r
276         \r
277         QE_ConvertDOSToUnixName( temp, filename );\r
278         \r
279         size = vfsLoadFullPathFile(filename, (void**)&data);\r
280   if (size <= 0)\r
281   {\r
282     Sys_FPrintf (SYS_ERR, "Eclass_ScanFile: %s not found\n", filename);\r
283     return;\r
284   }\r
285   Sys_Printf ("ScanFile: %s\n", temp);  \r
286   eclass_found = false;\r
287   for (i=0 ; i<size ; i++)\r
288   {\r
289     if (!strncmp(data+i, "/*QUAKED",8))\r
290     {\r
291       e = Eclass_InitFromText (data+i);\r
292       if (e)\r
293         Eclass_InsertAlphabetized (e);\r
294       else\r
295         Sys_FPrintf (SYS_ERR, "Error parsing: %s in %s\n",debugname, filename);\r
296       \r
297       // single ?\r
298       *Get_Eclass_E() = e;\r
299       Set_Eclass_Found(true);\r
300       if ( Get_Parsing_Single() )\r
301         break;\r
302     }\r
303   }\r
304     \r
305   g_free (data);                \r
306 }\r