Compare commits
10 Commits
a241dc857d
...
a0a8c3fff9
Author | SHA1 | Date | |
---|---|---|---|
|
a0a8c3fff9 | ||
|
c02f8da854 | ||
|
dde573d436 | ||
|
662f01150f | ||
|
3cb21258b8 | ||
|
e6511e3306 | ||
|
579b23fccb | ||
|
f88a4710f0 | ||
|
fc711448d8 | ||
|
957e262560 |
4
Makefile
4
Makefile
@ -1,6 +1,6 @@
|
||||
EX=reflex2q3
|
||||
CC=g++
|
||||
CFLAGS=-std=c++11 -I"include" -I"lib/Catch/single_include" -I"lib/cxxopts/include" -I"/usr/include/eigen3"
|
||||
CFLAGS=-std=c++11 -static -static-libgcc -static-libstdc++ -I"/mingw64/include/eigen3" -I"include" -I"lib/Catch/single_include" -I"lib/cxxopts/include" -I"/usr/include/eigen3"
|
||||
TESTEX=runtests
|
||||
|
||||
all: main test
|
||||
@ -28,5 +28,5 @@ EntityConverter.o: src/EntityConverter.cpp
|
||||
$(CC) -c $^ $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm *.o *.log $(EX)
|
||||
rm *.o $(EX)
|
||||
|
||||
|
@ -17,10 +17,10 @@ Converts Reflex maps (Version 8 and below) into id Tech map files. A pre-compil
|
||||
|
||||
#### Convert map geometry and entities:
|
||||
```bash
|
||||
./reflex2q3 [input].map [output].map -e [entity file].ent
|
||||
./reflex2q3 [input].map [output].map -e [entity file].rem
|
||||
```
|
||||
|
||||
We've provided Quake 3 and Xonotic entity conversion files (r2q3.ent and r2xonotic.ent). To create entity files for other games built on the [id Tech 3](https://en.wikipedia.org/wiki/Id_Tech_3) engine or previous [id Tech](https://en.wikipedia.org/wiki/Id_Tech) engines, refer to our [Reflex entity documentation](https://git.teknik.io/scuti/reflex2q3/src/f2b0341da38b82ad4f0a0cf258b0f6e6d8335fda/docs/doc-entities.txt), our sample .ent files, and relevant documentation for your game.
|
||||
We've provided Quake 3 and Xonotic entity conversion files (r2q3.rem and r2xonotic.rem). To create entity files for other games built on the [id Tech 3](https://en.wikipedia.org/wiki/Id_Tech_3) engine or previous [id Tech](https://en.wikipedia.org/wiki/Id_Tech) engines, refer to our [Reflex entity documentation](https://git.teknik.io/scuti/reflex2q3/src/f2b0341da38b82ad4f0a0cf258b0f6e6d8335fda/docs/doc-entities.txt), our sample .rem files, and relevant documentation for your game.
|
||||
|
||||
#### List all command line arguments:
|
||||
```bash
|
||||
|
@ -57,8 +57,8 @@ class EntityConverter
|
||||
* Method: Constructor
|
||||
* Description: Creates entity format mapping
|
||||
* CAUTION: Requires extractMapInfo method to be called after this
|
||||
* Requires: .ent filename for mapping entities from reflex format to xonotic format
|
||||
* THROWS: runtime_error on .ent format error
|
||||
* Requires: Reflex Entity Mapping filename
|
||||
* THROWS: runtime_error on Reflex Entity Mapping file format error
|
||||
* THROWS: std::ios::failure on IO failure
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
@ -69,7 +69,7 @@ class EntityConverter
|
||||
* Description: Creates entity format mapping and pre-scans for map info
|
||||
* Parameter: string entityMapFile, file maps source to target entity formats
|
||||
* Parameter: string reflexMapFile, for pre-scan
|
||||
* THROWS: runtime_error on .ent format error
|
||||
* THROWS: runtime_error on Reflex Entity Mapping file format error
|
||||
* THROWS: std::ios::failure on IO failure
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -25,12 +25,7 @@ void write(const std::vector<std::string> &,
|
||||
void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
|
||||
EntityConverter &);
|
||||
|
||||
void parse_prefab(std::ifstream &,
|
||||
std::ofstream &,
|
||||
void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
|
||||
std::vector<std::vector<std::string> > &);
|
||||
|
||||
bool convertmap(const char * const,
|
||||
bool convertmap(std::stringstream &,
|
||||
const char * const,
|
||||
void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
|
||||
std::vector<std::vector<std::string> > &);
|
||||
@ -180,4 +175,19 @@ using namespace std;
|
||||
return output;
|
||||
}
|
||||
|
||||
template <class ISTR>
|
||||
void parse_prefab(ISTR &f,
|
||||
std::ofstream &out,
|
||||
void (*b) (std::stringstream &, const std::vector<TPlanePoints> &),
|
||||
std::vector<std::vector<std::string> > &entities) {
|
||||
using namespace std;
|
||||
string l;
|
||||
getline(f, l);
|
||||
if (l.find(KEYWORD_BRUSH) != string::npos) {
|
||||
write(parse_brush<ISTR>(f), out, b);
|
||||
} else if (l.find(KEYWORD_ENTITY) != string::npos) {
|
||||
entities.push_back(get_entity<ISTR>(f));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1 +1 @@
|
||||
Subproject commit 27640a5a968a0981eeab5f354aa52459641b2e91
|
||||
Subproject commit d2d8455b571b6c66c4b7003500a77f9a93ecdc28
|
@ -1 +1 @@
|
||||
Subproject commit c2c2262626b20c75d1bebbab5e35d3f9282d7f63
|
||||
Subproject commit d7b930846cdccfc8bcecc4d7150ddcbadffac360
|
@ -33,9 +33,11 @@
|
||||
|
||||
|
||||
|
||||
EntityConverter::EntityConverter(const std::string &entityMapFile) :
|
||||
OFFSET_PLAYER(32.0), OFFSET_PICKUP(2.0), BRIGHTNESS_ADJUST(50.0),
|
||||
OUTPUT_PRECISION(10)
|
||||
EntityConverter::EntityConverter (const std::string &entityMapFile)
|
||||
: OFFSET_PLAYER(32.0),
|
||||
OFFSET_PICKUP(2.0),
|
||||
BRIGHTNESS_ADJUST(50.0),
|
||||
OUTPUT_PRECISION(6)
|
||||
{
|
||||
//MUST RUN extractMapInfo method after this constructor
|
||||
haveMapInfo_ = false;
|
||||
@ -53,7 +55,7 @@ EntityConverter::EntityConverter(const std::string &entityMapFile) :
|
||||
|
||||
EntityConverter::EntityConverter (const std::string &entityMapFile,
|
||||
const std::string &reflexMapFile) : OFFSET_PLAYER(32.0),
|
||||
OFFSET_PICKUP(2.0), BRIGHTNESS_ADJUST(50.0), OUTPUT_PRECISION(10)
|
||||
OFFSET_PICKUP(2.0), BRIGHTNESS_ADJUST(50.0), OUTPUT_PRECISION(6)
|
||||
{
|
||||
haveMapInfo_ = false;
|
||||
// game modes default to enabled
|
||||
@ -390,11 +392,7 @@ EntityConverter::convertPlayerSpawn(const std::vector<std::string> &lines) const
|
||||
}
|
||||
}
|
||||
else {
|
||||
convertedLines.push_back ( "\"classname\" \"info_player_race\"\n" );
|
||||
// Reflex maps have only start and finish, point to start on spawn
|
||||
convertedLines.push_back ( "\"target\" \"cp1\"\n" );
|
||||
// Reflex maps are only cts, set spawn to cts-only type
|
||||
convertedLines.push_back ( "\"race_place\" \"-1\"\n" );
|
||||
convertedLines.push_back ("\"classname\" \"info_player_start\"\n");
|
||||
}
|
||||
|
||||
std::stringstream positionStream;
|
||||
@ -516,7 +514,7 @@ EntityConverter::convertTarget(const std::vector<std::string> &lines) const
|
||||
if (haveName) {
|
||||
auto targetIter = targetMap_.find (targetName);
|
||||
if (targetIter == targetMap_.end()) {
|
||||
std::cerr << makeErrorMessage("End-game camera Target is not a supported feature in id Tech games. Skipping", lines);
|
||||
//std::cerr << makeErrorMessage ("End-game camera Target is not a supported feature in id Tech games. Skipping", lines);
|
||||
|
||||
std::vector<std::string> empty;
|
||||
return empty;
|
||||
@ -563,7 +561,8 @@ EntityConverter::convertRaceStart(const std::vector<std::string> &lines) const
|
||||
std::vector<std::string> convertedLines;
|
||||
convertedLines.push_back ("\"classname\" \"trigger_race_checkpoint\"\n");
|
||||
convertedLines.push_back ("\"targetname\" \"cp1\"\n");
|
||||
convertedLines.push_back ("\"cnt\" \"1\"\n");
|
||||
// While 0 is finish in Race, in CTS, checkpoints numbered from 0 to n
|
||||
convertedLines.push_back ("\"cnt\" \"0\"\n");
|
||||
return convertedLines;
|
||||
}
|
||||
|
||||
@ -575,7 +574,8 @@ EntityConverter::convertRaceFinish(const std::vector<std::string> &lines) const
|
||||
std::vector<std::string> convertedLines;
|
||||
convertedLines.push_back ("\"classname\" \"trigger_race_checkpoint\"\n");
|
||||
convertedLines.push_back ("\"targetname\" \"finish\"\n");
|
||||
convertedLines.push_back ("\"cnt\" \"0\"\n");
|
||||
// While 0 is finish in Race, in CTS, checkpoints numbered from 0 to n
|
||||
convertedLines.push_back ("\"cnt\" \"1\"\n");
|
||||
return convertedLines;
|
||||
}
|
||||
|
||||
@ -682,7 +682,7 @@ EntityConverter::mapEntities(const std::string &mapFile)
|
||||
fin.open (mapFile);
|
||||
|
||||
if (fin.is_open()) {
|
||||
//Read .ent contents into pickup map
|
||||
//Read Reflex Entity Mapping file contents into pickup map
|
||||
std::string line;
|
||||
while (std::getline (fin, line)) {
|
||||
std::istringstream iss (line);
|
||||
@ -696,7 +696,7 @@ EntityConverter::mapEntities(const std::string &mapFile)
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw std::ios::failure( "Error: EntityConverter failed to open .ent file" );
|
||||
throw std::ios::failure ("Error: EntityConverter failed to open Reflex Entity Mapping file");
|
||||
}
|
||||
fin.close();
|
||||
|
||||
|
34
src/main.cpp
34
src/main.cpp
@ -16,6 +16,7 @@
|
||||
|
||||
#include "oopless-parser.hpp"
|
||||
#include "brushdef.hpp"
|
||||
#include <iterator>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -57,6 +58,22 @@ cxxopts::Options arguments(int ac, char ** av) {
|
||||
return o;
|
||||
}
|
||||
|
||||
stringstream loadmap(const char *filename) {
|
||||
ifstream fin;
|
||||
fin.open(filename);
|
||||
if (!fin.good()) {
|
||||
cout << "error: can not open input file." << endl;
|
||||
}
|
||||
vector<string> v;
|
||||
string line;
|
||||
stringstream output;
|
||||
while (getline(fin, line)) {
|
||||
v.push_back(line);
|
||||
}
|
||||
move(v.begin(), v.end(), ostream_iterator<string>(output, "\n"));
|
||||
return output;
|
||||
}
|
||||
|
||||
bool convert_worldspawn(const cxxopts::Options &o,
|
||||
vector<vector<string> > &q) {
|
||||
bool is_ok = false;
|
||||
@ -64,9 +81,11 @@ bool convert_worldspawn(const cxxopts::Options &o,
|
||||
if (o.count(ARG_BRUSHFORMAT)) {
|
||||
fn = &brushdef_gtk;
|
||||
}
|
||||
string inputfile = o[ARG_INPUT_SHORTALIAS].as<string>();
|
||||
stringstream mapdata = loadmap(inputfile.c_str());
|
||||
try {
|
||||
is_ok = convertmap(
|
||||
o[ARG_INPUT_SHORTALIAS].as<string>().c_str(), // in file
|
||||
mapdata, // in file
|
||||
o[ARG_OUTPUT_SHORTALIAS].as<string>().c_str(), // out file
|
||||
fn, // brush definition
|
||||
q); // queue of entities
|
||||
@ -126,11 +145,22 @@ void convert_entities(const cxxopts::Options &o, const vector<vector<string> > &
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try {
|
||||
cxxopts::Options p = arguments(argc, argv);
|
||||
|
||||
vector<vector<string> > entities;
|
||||
bool is_ok = convert_worldspawn(p, entities);
|
||||
// print_entities(entities);
|
||||
convert_entities(p, entities);
|
||||
}
|
||||
catch (cxxopts::option_not_exists_exception e) {
|
||||
cerr << e.what() << endl
|
||||
<< "./reflex2q3 -h for usage information" << endl;
|
||||
return -1;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
cerr << e.what() << endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -101,29 +101,10 @@ void write(const vector<string> &entity,
|
||||
fo << "}" << endl;
|
||||
}
|
||||
|
||||
void parse_prefab(ifstream &f,
|
||||
ofstream &out,
|
||||
void (*b) (stringstream &, const vector<TPlanePoints> &),
|
||||
vector<vector<string> > &entities) {
|
||||
string l;
|
||||
getline(f, l);
|
||||
if (l.find(KEYWORD_BRUSH) != string::npos) {
|
||||
write(parse_brush<ifstream>(f), out, b);
|
||||
} else if (l.find(KEYWORD_ENTITY) != string::npos) {
|
||||
entities.push_back(get_entity<ifstream>(f));
|
||||
}
|
||||
}
|
||||
|
||||
bool convertmap(const char * const infile,
|
||||
bool convertmap(stringstream &mapdata,
|
||||
const char * const outfile,
|
||||
void (*brushdef) (stringstream &, const vector<TPlanePoints> &),
|
||||
vector<vector<string> > &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()) {
|
||||
@ -133,18 +114,17 @@ bool convertmap(const char * const infile,
|
||||
fout << "{\n"
|
||||
<< "\"classname\" \"worldspawn\"" << endl;
|
||||
string line;
|
||||
while (getline(fin, line)) {
|
||||
while (getline(mapdata, line)) {
|
||||
if (line.find(KEYWORD_PREFAB) != string::npos ||
|
||||
line.find(KEYWORD_GLOBAL) != string::npos) {
|
||||
parse_prefab(fin, fout, brushdef, entities);
|
||||
parse_prefab<stringstream>(mapdata, fout, brushdef, entities);
|
||||
} else if (line.find(KEYWORD_ENTITY) != string::npos) {
|
||||
entities.push_back(get_entity<ifstream>(fin));
|
||||
entities.push_back(get_entity<stringstream>(mapdata));
|
||||
} else if (line.find(KEYWORD_BRUSH) != string::npos) {
|
||||
write(parse_brush<ifstream>(fin), fout, brushdef);
|
||||
write(parse_brush<stringstream>(mapdata), fout, brushdef);
|
||||
}
|
||||
}
|
||||
fout << "}" << endl;
|
||||
fin.close();
|
||||
fout.close();
|
||||
return true;
|
||||
}
|
||||
|
@ -5,12 +5,12 @@
|
||||
*
|
||||
* Description: Unit tests for EntityConverter class
|
||||
*
|
||||
* Version: 0.1
|
||||
* Version: 1.0
|
||||
* Created: 07/14/2017 20:36:31 PM
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: suhrke@teknik.io
|
||||
* Author: surkeh@protonmail.com
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
#include "EntityConverter.hpp"
|
||||
|
||||
#define ENTITY_FILENAME "r2xonotic.ent"
|
||||
#define ENTITY_FILENAME "r2xonotic.rem"
|
||||
#define DELTA 0.00001
|
||||
|
||||
|
||||
@ -129,12 +129,10 @@ TEST_CASE( "r2x: a single PlayerSpawn (race) entity can be converted", "[EntityC
|
||||
std::vector<std::string> unused = ec.convert(worldspawn);
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
|
||||
REQUIRE( converted[0] == "\"classname\" \"info_player_race\"\n" );
|
||||
REQUIRE( converted[1] == "\"target\" \"cp1\"\n" );
|
||||
REQUIRE( converted[2] == "\"race_place\" \"-1\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"info_player_start\"\n");
|
||||
|
||||
// The z (vertical) is offset by +32
|
||||
std::istringstream iss(converted[3]);
|
||||
std::istringstream iss (converted[1]);
|
||||
std::string attribute;
|
||||
std::string coords[2];
|
||||
float offsetCoord;
|
||||
@ -146,7 +144,7 @@ TEST_CASE( "r2x: a single PlayerSpawn (race) entity can be converted", "[EntityC
|
||||
REQUIRE (fabs(-100.00000 - offsetCoord) <= DELTA);
|
||||
|
||||
SECTION( "Converted angles are valid (Different coordinate system handedness)") {
|
||||
std::istringstream angleLineStream(converted[4]);
|
||||
std::istringstream angleLineStream(converted[2]);
|
||||
std::string angleAttribute;
|
||||
std::string a;
|
||||
float angle;
|
||||
@ -279,7 +277,7 @@ TEST_CASE( "r2x: a single RaceStart entity can be converted", "[EntityConverter]
|
||||
|
||||
REQUIRE (converted[0] == "\"classname\" \"trigger_race_checkpoint\"\n");
|
||||
REQUIRE (converted[1] == "\"targetname\" \"cp1\"\n");
|
||||
REQUIRE( converted[2] == "\"cnt\" \"1\"\n" );
|
||||
REQUIRE (converted[2] == "\"cnt\" \"0\"\n");
|
||||
}
|
||||
|
||||
|
||||
@ -305,7 +303,7 @@ TEST_CASE( "r2x: a single RaceFinish entity can be converted", "[EntityConverter
|
||||
|
||||
REQUIRE (converted[0] == "\"classname\" \"trigger_race_checkpoint\"\n");
|
||||
REQUIRE (converted[1] == "\"targetname\" \"finish\"\n");
|
||||
REQUIRE( converted[2] == "\"cnt\" \"0\"\n" );
|
||||
REQUIRE (converted[2] == "\"cnt\" \"1\"\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: suhrke@teknik.io
|
||||
* Author: surkeh@protonmail.com
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user