void EntityClassScannerUFO::scanFile (EntityClassCollector& collector) { const std::string& filename = getFilename(); AutoPtr<ArchiveTextFile> file(GlobalFileSystem().openTextFile(filename)); if (!file) { std::string buffer = "Could not load " + filename; gtkutil::errorDialog(buffer); return; } const std::size_t size = file->size(); char* entities = (char*) malloc(size + 1); TextInputStream &stream = file->getInputStream(); const std::size_t realsize = stream.read(entities, size); entities[realsize] = '\0'; if (ED_Parse(entities) == ED_ERROR) { std::string buffer = "Parsing of entities definition file failed, returned error was " + std::string( ED_GetLastError()); gtkutil::errorDialog(buffer); } else { for (int i = 0; i < numEntityDefs; i++) { EntityClass *e = initFromDefinition(&entityDefs[i]); if (e) collector.insert(e); } } free(entities); ED_Free(); }
/** * @brief check alignment using abstract size and mandatory origin * @return true if OK * @todo check for brush intersection as well as alignment, and move * to a good position if bad. */ static bool Check_InfoStartAligned (const entityDef_t* ed, const entity_t* e) { static int size[6]; const entityKeyDef_t* sizeKd = ED_GetKeyDefEntity(ed, "size", 1); /* 1 means find abstract version of key */ if (ED_GetIntVector(sizeKd, size, (int)(sizeof(size) / sizeof(int))) == ED_ERROR) Sys_Error("%s", ED_GetLastError()); return (((int)e->origin[0] - size[0]) % UNIT_SIZE == 0) && (((int)e->origin[1] - size[1]) % UNIT_SIZE == 0); }
/** * @note Check_Free calls ED_Free, which frees all outstanding * malloc'd space from this function */ void Check_InitEntityDefs (void) { char *entitiesUfoBuf; /* only do this once, may be called by different * check functions, depending on command-line */ if (numEntityDefs) return; if (FS_LoadFile("ufos/entities.ufo", (byte **)&entitiesUfoBuf) == -1) Sys_Error("CheckEntities: Unable to read entities.ufo"); if (ED_Parse((const char *)entitiesUfoBuf) == ED_ERROR) Sys_Error("Error while parsing entities.ufo: %s", ED_GetLastError()); /* info has been copied to new malloc'd space in ED_Parse */ Mem_Free(entitiesUfoBuf); }
/** * @brief Perform an entity check */ void CheckEntities (void) { Check_InitEntityDefs(); for (int i = 0; i < num_entities; i++) { entity_t* e = &entities[i]; const char* name = ValueForKey(e, "classname"); const entityDef_t* ed = ED_GetEntityDef(name); const epair_t* kvp; const entityKeyDef_t* kd; if (!ed) { /* check that a definition exists */ Check_Printf(VERB_CHECK, false, i, -1, "Not defined in entities.ufo: %s\n", name); continue; } /* check alignment of info_.+_start */ if (Check_IsInfoStart(name) && !Check_InfoStartAligned(ed, e)) Check_Printf(VERB_CHECK, false, i, -1, "Misaligned %s\n", name); if (Q_strstart(name, "func_")) /* func_* entities should have brushes */ Check_EntityWithBrushes(e, name, i); /* check all keys in the entity - make sure they are OK */ for (kvp = e->epairs; kvp; kvp = kvp->next) { kd = ED_GetKeyDefEntity(ed, kvp->key, 0); /* zero means ignore abstract (radiant only) keys */ if (!kd) { /* make sure it has a definition */ Check_Printf(VERB_CHECK, false, i, -1, "Not defined in entities.ufo: %s in %s\n", kvp->key, name); continue; } if (ED_CheckKey(kd, kvp->value) == ED_ERROR) { /* check values against type and range definitions in entities.ufo */ Check_Printf(VERB_CHECK, false, i, -1, "%s\n", ED_GetLastError()); continue; } if (Q_streq("target", kvp->key) || Q_streq("targetname", kvp->key)) { if (!Check_TargetExists(kvp)) { Check_Printf(VERB_CHECK, false, i, -1, "%s with %s of %s: no corresponding entity with %s with matching value\n", ed->classname, kvp->key, kvp->value, Q_streq("target", kvp->key) ? "targetname" : "target"); } } } /* check keys in the entity definition - make sure mandatory ones are present */ for (kd = ed->keyDefs; kd->name; kd++) { if (kd->flags & ED_MANDATORY) { const char* keyNameInEnt = ValueForKey(e, kd->name); if (keyNameInEnt[0] == '\0') { const char* defaultVal = kd->defaultVal; const bool hasDefault = defaultVal ? true : false; Check_Printf(VERB_CHECK, hasDefault, i, -1, "Mandatory key missing from entity: %s in %s", kd->name, name); if (defaultVal) { Check_Printf(VERB_CHECK, hasDefault, i, -1, ", supplying default: %s", defaultVal); SetKeyValue(e, kd->name, defaultVal); } Check_Printf(VERB_CHECK, hasDefault, i, -1, "\n"); } } } } }