#include "oopless-parser.hpp" #include "brushdef.hpp" #include #include #include using namespace std; bool is_ebrush(const std::vector &input) { #define KEYWORD_ENTBRUSH1 "type Teleporter" #define KEYWORD_ENTBRUSH2 "type JumpPad" #define KEYWORD_ENTBRUSH3 "type RaceStart" #define KEYWORD_ENTBRUSH4 "type RaceFinish" for (const string &str : input) { if (str.find(KEYWORD_ENTBRUSH1) != string::npos || str.find(KEYWORD_ENTBRUSH2) != string::npos || str.find(KEYWORD_ENTBRUSH3) != string::npos || str.find(KEYWORD_ENTBRUSH4) != string::npos) { return true; } } return false; } // place holding functions to test proper control flow. bool write(const struct TBrush &geometry, ofstream &fout, void (*b) (stringstream &, const vector &)) { bool ok = true; if (geometry.m_Vertices.size() < 1) { cerr << "error: geometry has no vertices" << endl; ok = false; } if (geometry.m_Faces.size() < 1) { cerr << "error: geometry has no faces"<< endl; ok = false; } if (ok) { fout << GetBrushString(geometry, b); } return ok; } // currently for the specific case to specify trigger to brush entities struct TBrush override_textures(struct TBrush x, const char *texture) { struct TBrush output = x; for (struct TFace &z : output.m_Faces) { // prevent appending color infomation to texture file path // may need re-ordering on when to append that. z.hex = string(); z.m_Material = texture; } return output; } void write(const vector &entity, ofstream &fo, void (*b) (stringstream &, const vector &), EntityConverter &e) { /* Likely inefficient. Current process for the entities: 1. It acquires the lines. 2. Searches through and splits the vector. 3. Recombines the brush vector. (4. Sends the vector to parse the brush through again.)*/ bool brushent = false; unsigned int i; for (i = 0; i < entity.size(); ++i) { if (entity[i].find(KEYWORD_BRUSH) != string::npos) { brushent = true; break; } } vector brush(entity.size() - i); if (brushent) { // entity.begin() + i = vector that begins with KEYWORD_BRUSH // parsing functions will expect only the contents underneath the keyword. move((entity.begin() + i), entity.end(), brush.begin()); } vector converted = e.convert(entity); if (converted.empty()) { return; } fo << "{" << endl; for (const string &s : converted) { fo << s; } if (brushent) { stringstream ss; string line; copy(brush.begin(), brush.end(), ostream_iterator(ss, "\n")); getline(ss, line); // this both discards the brush keyboard and prevents a crash write(override_textures(parse_brush(ss), "common/trigger"), fo, b); } fo << "}" << endl; } // entities will vary widely depending on their type and available flags. // for now, acquire entity data, and handle their conversion in the write methods. vector get_entity(ifstream &f) { vector output; string line; unsigned int pos = f.tellg(); while (getline(f, line)) { // stop when // entity or a prefab keyword // brush keyword and the entity is not of the type teleporter or jumppad. if ((line.find(KEYWORD_ENTITY) != string::npos || line.find(KEYWORD_PREFAB) != string::npos) || ( line.find(KEYWORD_BRUSH) != string::npos && !is_ebrush(output))) { f.seekg(pos); return output; } else { output.push_back(line); } pos = f.tellg(); } } void parse_prefab(ifstream &f, ofstream &out, void (*b) (stringstream &, const vector &), vector > &entities) { string l; getline(f, l); if (l.find(KEYWORD_BRUSH) != string::npos) { write(parse_brush(f), out, b); } else if (l.find(KEYWORD_ENTITY) != string::npos) { entities.push_back(get_entity(f)); } } bool convertmap(const char * const infile, const char * const outfile, void (*brushdef) (stringstream &, const vector &), vector > &entities) { ifstream fin; fin.open(infile); if (!fin.good()){ cerr << "error: failed to open input file" << endl; return false; } ofstream fout; fout.open(outfile); if (!fout.good()) { cerr << "error: failed to open output file" << endl; return false; } fout << "{\n" << "\"classname\" \"worldspawn\"" << endl; string line; while (getline(fin, line)) { if (line.find(KEYWORD_PREFAB) != string::npos || line.find(KEYWORD_GLOBAL) != string::npos) { parse_prefab(fin, fout, brushdef, entities); } else if (line.find(KEYWORD_ENTITY) != string::npos) { entities.push_back(get_entity(fin)); } else if (line.find(KEYWORD_BRUSH) != string::npos) { write(parse_brush(fin), fout, brushdef); } } fout << "}" << endl; fin.close(); fout.close(); return true; }