#include #include "QF/dstring.h" #include "QF/quakeio.h" #include "QF/script.h" #include "QF/sys.h" #include "QF/va.h" #include "EntityClass.h" @implementation EntityClass static int parse_vector (script_t *script, vec3_t vec) { int r; if (!Script_GetToken (script, 0)) return 0; if (strcmp (script->token->str, "(")) return 0; r = sscanf (script->p, "%f %f %f)", &vec[0], &vec[1], &vec[2]); if (r != 3) return 0; while (strcmp (script->token->str, ")")) { if (!Script_GetToken (script, 0)) return 0; } return 1; } // the classname, color triple, and bounding box are parsed out of comments // A ? size means take the exact brush size. // // /*QUAKED (0 0 0) ? // /*QUAKED (0 0 0) (-8 -8 -8) (8 8 8) // // Flag names can follow the size description: // // /*QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK GOLD_KEY SILVER_KEY - initFromText: (const char *)text source: (const char *)filename { const char *t; size_t len; int i; script_t *script; [super init]; text += strlen("/*QUAKED "); script = Script_New (); Script_Start (script, filename, text); // grab the name if (!Script_GetToken (script, 0)) return 0; if (!strcmp (script->token->str, "*/")) return 0; name = strdup (script->token->str); // grab the color if (!parse_vector (script, color)) return 0; // get the size if (!strcmp (script->token->str, "(")) { Script_UngetToken (script); if (!parse_vector (script, mins)) return 0; if (!parse_vector (script, maxs)) return 0; esize = esize_fixed; } else if (!strcmp (script->token->str, "?")) { // use the brushes esize = esize_model; } else { return 0; } // get the flags // any remaining words on the line are parm flags for (i = 0; i < MAX_FLAGS; i++) { if (!Script_TokenAvailable (script, 0)) break; Script_GetToken (script, 0); flagnames[i] = strdup (script->token->str); } while (Script_TokenAvailable (script, 0)) Script_GetToken (script, 0); // find the length until close comment for (t = script->p; t[0] && !(t[0] == '*' && t[1] == '/'); t++) ; // copy the comment block out len = t - text; comments = malloc (len + 1); memcpy (comments, text, len); comments[len] = 0; return self; } - (esize_t)esize { return esize; } - (char *)classname { return name; } - (float *)mins { return mins; } - (float *)maxs { return maxs; } - (float *)drawColor { return color; } - (char *)comments { return comments; } - (char *)flagName: (unsigned)flagnum { if (flagnum >= MAX_FLAGS) Sys_Error ("EntityClass flagName: bad number"); return flagnames[flagnum]; } @end //=========================================================================== @implementation EntityClassList /* ================= insertEC: ================= */ - (void)insertEC: ec { char *name; int i; name = [ec classname]; for (i=0 ; i<[self count] ; i++) { if (strcasecmp (name, [[self objectAtIndex: i] classname]) < 0) { [self insertObject: ec atIndex:i]; return; } } [self addObject: ec]; } /* ================= scanFile ================= */ - (void)scanFile: (char *)filename { int size, line; char *data; id cl; int i; char path[1024]; QFile *file; sprintf (path,"%s/%s", source_path, filename); file = Qopen (path, "rt"); if (!file) return; size = Qfilesize (file); data = malloc (size + 1); size = Qread (file, data, size); data[size] = 0; Qclose (file); line = 1; for (i=0 ; id_name); if (len <= 3) continue; if (!strcmp (ent->d_name+len-3,".qc")) [self scanFile: ent->d_name]; } } id entity_classes_i; - initForSourceDirectory: (char *)path { [super init]; source_path = path; [self scanDirectory]; entity_classes_i = self; nullclass = [[EntityClass alloc] initFromText: "/*QUAKED UNKNOWN_CLASS (0 0.5 0) ?*/" source: va ("%s:%d", __FILE__, __LINE__ - 1)]; return self; } - (id)classForName: (char *)name { int i; id o; for (i=0 ; i<[self count] ; i++) { o = [self objectAtIndex: i]; if (!strcmp (name,[o classname]) ) return o; } return nullclass; } @end