broke apart EntityConverter::convert, added submodule
This commit is contained in:
parent
757daa6dd1
commit
225e1375ef
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "ReflexToQ3/includes/cxxopts"]
|
||||||
|
path = ReflexToQ3/includes/cxxopts
|
||||||
|
url = https://github.com/jarro2783/cxxopts.git
|
2
ReflexToQ3/.gitignore
vendored
2
ReflexToQ3/.gitignore
vendored
@ -6,4 +6,4 @@
|
|||||||
*.log
|
*.log
|
||||||
|
|
||||||
# executables
|
# executables
|
||||||
reflex2q3_*
|
reflex2q3
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
EX=reflex2q3
|
EX=reflex2q3
|
||||||
CC=g++
|
CC=g++
|
||||||
CFLAGS=-std=c++11 -I"includes" -I"/usr/include/eigen3"
|
CFLAGS=-std=c++11 -I"./includes" -I"./includes/cxxopts/include" -I"/usr/include/eigen3"
|
||||||
TESTEX=test/test-parser
|
TESTEX=test/test-parser
|
||||||
|
|
||||||
all: main test
|
all: main
|
||||||
|
|
||||||
main: planes.o brushdef.o oopless-parser.o EntityConverter.o
|
main: planes.o brushdef.o oopless-parser.o EntityConverter.o
|
||||||
$(CC) $^ main.cpp $(CFLAGS) -o $(EX) 2>error8.log
|
$(CC) $^ main.cpp $(CFLAGS) -o $(EX) 2>error8.log
|
||||||
|
@ -24,44 +24,36 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
* PUBLIC
|
||||||
|
*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
EntityConverter::EntityConverter(std::string entityMapFile)
|
||||||
|
{
|
||||||
|
//MUST RUN matchRelated method after this constructor
|
||||||
|
areEntitiesMatched_ = false;
|
||||||
|
mapEntities(entityMapFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EntityConverter::EntityConverter(std::string entityMapFile, std::string reflexMapFile)
|
EntityConverter::EntityConverter(std::string entityMapFile, std::string reflexMapFile)
|
||||||
{
|
{
|
||||||
//Open .ent mapping file
|
mapEntities(entityMapFile);
|
||||||
std::ifstream entFin;
|
|
||||||
entFin.open(entityMapFile);
|
|
||||||
|
|
||||||
if ( entFin.is_open() ) {
|
// Pre-scan for related entities
|
||||||
//Read .ent contents into pickup map
|
std::ifstream fin;
|
||||||
std::string line;
|
fin.open(reflexMapFile);
|
||||||
while (std::getline(entFin, line)) {
|
|
||||||
std::istringstream iss(line);
|
|
||||||
// Reflex ID corresponds to xonotic pickup name
|
|
||||||
int id;
|
|
||||||
std::string pickup;
|
|
||||||
if ( ! (iss >> id >> pickup)) {
|
|
||||||
throw std::runtime_error( "format error in .ent file" );
|
|
||||||
}
|
|
||||||
pickupMapping_.insert ( std::pair<int, std::string>(id, pickup) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw std::ios::failure( "Error: EntityConverter failed to open .ent file" );
|
|
||||||
}
|
|
||||||
entFin.close();
|
|
||||||
|
|
||||||
|
if ( fin.is_open() ) {
|
||||||
//Open .map file
|
|
||||||
std::ifstream mapFin;
|
|
||||||
mapFin.open(reflexMapFile);
|
|
||||||
|
|
||||||
if ( mapFin.is_open() ) {
|
|
||||||
//Extract the source type of targets (teleporters or jump pads)
|
//Extract the source type of targets (teleporters or jump pads)
|
||||||
std::string line;
|
std::string line;
|
||||||
std::string trash;
|
std::string trash;
|
||||||
std::string targetName;
|
std::string targetName;
|
||||||
while (std::getline(mapFin, line)) {
|
while (std::getline(fin, line)) {
|
||||||
if ( line.find("type Teleporter") != std::string::npos) {
|
if ( line.find("type Teleporter") != std::string::npos) {
|
||||||
std::getline(mapFin, line);
|
std::getline(fin, line);
|
||||||
std::istringstream iss(line);
|
std::istringstream iss(line);
|
||||||
if ( ! (iss >> trash >> trash >> targetName)) {
|
if ( ! (iss >> trash >> trash >> targetName)) {
|
||||||
throw std::runtime_error( "format error in .map file");
|
throw std::runtime_error( "format error in .map file");
|
||||||
@ -69,7 +61,7 @@ EntityConverter::EntityConverter(std::string entityMapFile, std::string reflexMa
|
|||||||
targetMap_.insert ( std::pair<std::string, std::string>(targetName, "Teleporter") );
|
targetMap_.insert ( std::pair<std::string, std::string>(targetName, "Teleporter") );
|
||||||
}
|
}
|
||||||
else if ( line.find("type JumpPad") != std::string::npos) {
|
else if ( line.find("type JumpPad") != std::string::npos) {
|
||||||
std::getline(mapFin, line);
|
std::getline(fin, line);
|
||||||
std::istringstream iss(line);
|
std::istringstream iss(line);
|
||||||
if ( ! (iss >> trash >> trash >> targetName)) {
|
if ( ! (iss >> trash >> trash >> targetName)) {
|
||||||
throw std::runtime_error( "format error in .map file");
|
throw std::runtime_error( "format error in .map file");
|
||||||
@ -81,7 +73,8 @@ EntityConverter::EntityConverter(std::string entityMapFile, std::string reflexMa
|
|||||||
else {
|
else {
|
||||||
throw std::ios::failure( "Error: EntityConverter failed to open .map file" );
|
throw std::ios::failure( "Error: EntityConverter failed to open .map file" );
|
||||||
}
|
}
|
||||||
mapFin.close();
|
fin.close();
|
||||||
|
areEntitiesMatched_ = true;
|
||||||
|
|
||||||
//DEBUG
|
//DEBUG
|
||||||
//printMapping();
|
//printMapping();
|
||||||
@ -89,24 +82,61 @@ EntityConverter::EntityConverter(std::string entityMapFile, std::string reflexMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
void EntityConverter::printMapping()
|
|
||||||
{
|
|
||||||
std::map<int, std::string>::iterator it;
|
|
||||||
for (it=pickupMapping_.begin(); it!=pickupMapping_.end(); ++it)
|
|
||||||
std::cout << it->first << " => " << it->second << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEBUG
|
std::vector<std::string>
|
||||||
void EntityConverter::printTargetSources()
|
EntityConverter::convert(std::vector<std::string> lines)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string>::iterator it;
|
if ( areEntitiesMatched_ )
|
||||||
for (it=targetMap_.begin(); it!=targetMap_.end(); ++it)
|
{
|
||||||
std::cout << it->first << " => " << it->second << std::endl;
|
std::string attribute;
|
||||||
|
std::string trash; //unused tokens
|
||||||
|
|
||||||
|
std::string type;
|
||||||
|
if ( lines.size() < 1 ) {
|
||||||
|
throw std::runtime_error("error: empty entity cannot be converted");
|
||||||
|
}
|
||||||
|
// second token is the type
|
||||||
|
std::istringstream iss(lines[0]);
|
||||||
|
if ( ! (iss >> trash >> type)) {
|
||||||
|
throw std::runtime_error("error: type is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( type == "Pickup" ) {
|
||||||
|
return convertPickup(lines);
|
||||||
|
}
|
||||||
|
else if ( type == "PlayerSpawn" ) {
|
||||||
|
return convertPlayerSpawn(lines);
|
||||||
|
}
|
||||||
|
else if ( type == "JumpPad" ) {
|
||||||
|
return convertJumpPad(lines);
|
||||||
|
}
|
||||||
|
else if ( type == "Teleporter" ) {
|
||||||
|
return convertTeleporter(lines);
|
||||||
|
}
|
||||||
|
else if ( type == "Target" ) {
|
||||||
|
return convertTarget(lines);
|
||||||
|
}
|
||||||
|
else if ( type == "RaceStart" ) {
|
||||||
|
return convertRaceStart(lines);
|
||||||
|
}
|
||||||
|
else if ( type == "RaceFinish" ) {
|
||||||
|
return convertRaceFinish(lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error( "error: related entities must be matched prior to conversion" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string EntityConverter::getAttributeType(std::string line)
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
* PRIVATE
|
||||||
|
*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
std::string
|
||||||
|
EntityConverter::getAttributeType(std::string line)
|
||||||
{
|
{
|
||||||
std::string type;
|
std::string type;
|
||||||
std::string dataType;
|
std::string dataType;
|
||||||
@ -120,186 +150,260 @@ std::string EntityConverter::getAttributeType(std::string line)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::string> EntityConverter::convert(std::vector<std::string> lines)
|
void
|
||||||
|
EntityConverter::mapEntities(std::string mapFile)
|
||||||
|
{
|
||||||
|
std::ifstream fin;
|
||||||
|
fin.open(mapFile);
|
||||||
|
|
||||||
|
if ( fin.is_open() ) {
|
||||||
|
//Read .ent contents into pickup map
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(fin, line)) {
|
||||||
|
std::istringstream iss(line);
|
||||||
|
// Reflex ID corresponds to xonotic pickup name
|
||||||
|
int id;
|
||||||
|
std::string pickup;
|
||||||
|
if ( ! (iss >> id >> pickup)) {
|
||||||
|
throw std::runtime_error( "format error in .ent file" );
|
||||||
|
}
|
||||||
|
pickupMapping_.insert ( std::pair<int, std::string>(id, pickup) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::ios::failure( "Error: EntityConverter failed to open .ent file" );
|
||||||
|
}
|
||||||
|
fin.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string>
|
||||||
|
EntityConverter::convertPickup(std::vector<std::string> &lines)
|
||||||
{
|
{
|
||||||
std::vector<std::string> convertedLines;
|
std::vector<std::string> convertedLines;
|
||||||
std::string coords[3];
|
std::string coords[3];
|
||||||
std::string attribute;
|
std::string trash;
|
||||||
std::string trash; //unused tokens
|
|
||||||
|
|
||||||
std::string type;
|
if ( lines.size() < 3 ) {
|
||||||
if ( lines.size() < 1 ) {
|
throw std::runtime_error("error: Pickup entity requires at least 3 lines");
|
||||||
std::cerr << "error: empty entity cannot be converted" << std::endl;
|
}
|
||||||
|
//can ignore angle of pickups in xonotic format
|
||||||
|
int pickupID;
|
||||||
|
bool havePosition = false;
|
||||||
|
bool havePickupID = false;
|
||||||
|
|
||||||
|
for (int i = 1; i < lines.size(); i++) {
|
||||||
|
std::string type = getAttributeType(lines[i]);
|
||||||
|
if ( type == "position" ) {
|
||||||
|
std::istringstream iss(lines[i]);
|
||||||
|
// Vector3 position coord0 coord1 coord2
|
||||||
|
if ( ! (iss >> trash >> trash >>
|
||||||
|
coords[0] >> coords[1] >> coords[2])) {
|
||||||
|
throw std::runtime_error("error: Pickup entity requires coordinates");
|
||||||
|
}
|
||||||
|
havePosition = true;
|
||||||
|
}
|
||||||
|
else if ( type == "pickupType" ) {
|
||||||
|
std::istringstream iss(lines[i]);
|
||||||
|
// UInt8 pickupType ID
|
||||||
|
if ( ! (iss >> trash >> trash >> pickupID) ) {
|
||||||
|
throw std::runtime_error("error: Pickup entity requires Pickup ID");
|
||||||
|
}
|
||||||
|
havePickupID = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( havePosition && havePickupID ) {
|
||||||
|
std::stringstream oss;
|
||||||
|
oss << "\"classname\" \"" << pickupMapping_[pickupID] << "\"" << std::endl;
|
||||||
|
convertedLines.push_back ( oss.str() );
|
||||||
|
// coordinates reordered to x, z, y
|
||||||
|
std::stringstream oss2;
|
||||||
|
oss2 << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
|
||||||
|
coords[1] << "\"" << std::endl;
|
||||||
|
convertedLines.push_back ( oss2.str() );
|
||||||
return convertedLines;
|
return convertedLines;
|
||||||
}
|
}
|
||||||
// second token is the type
|
else {
|
||||||
std::istringstream iss(lines[0]);
|
throw std::runtime_error("error: Pickup requires position and pickup ID, missing 1 or both");
|
||||||
if ( ! (iss >> trash >> type)) {
|
}
|
||||||
std::cerr << "error: type is required" << std::endl;
|
}
|
||||||
return convertedLines;
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string>
|
||||||
|
EntityConverter::convertPlayerSpawn(std::vector<std::string> &lines)
|
||||||
|
{
|
||||||
|
//minimum of 3 lines, max of ? lines
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string>
|
||||||
|
EntityConverter::convertJumpPad(std::vector<std::string> &lines)
|
||||||
|
{
|
||||||
|
std::vector<std::string> convertedLines;
|
||||||
|
std::string trash;
|
||||||
|
|
||||||
|
if ( lines.size() < 2 ) {
|
||||||
|
throw std::runtime_error("error: JumpPad entity requires at least 2 lines");
|
||||||
|
}
|
||||||
|
std::istringstream iss(lines[1]);
|
||||||
|
std::string targetName;
|
||||||
|
// String32 target targetName
|
||||||
|
if ( ! (iss >> trash >> trash >> targetName) ) {
|
||||||
|
throw std::runtime_error("error: JumpPad entity requires target name");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( type == "Pickup" ) { ////PICKUP
|
convertedLines.push_back ( "\"classname\" \"trigger_push\"\n" );
|
||||||
if ( lines.size() < 3 ) {
|
std::stringstream oss;
|
||||||
std::cerr << "error: Pickup entity requires at least 3 lines" << std::endl;
|
oss << "\"target\" \"" << targetName << "\"" << std::endl;
|
||||||
return convertedLines;
|
convertedLines.push_back ( oss.str() );
|
||||||
}
|
return convertedLines;
|
||||||
//can ignore angle of pickups in xonotic format
|
}
|
||||||
int pickupID;
|
|
||||||
bool havePosition = false;
|
|
||||||
bool havePickupID = false;
|
|
||||||
|
|
||||||
for (int i = 1; i < lines.size(); i++) {
|
|
||||||
type = getAttributeType(lines[i]);
|
|
||||||
if ( type == "position" ) {
|
std::vector<std::string>
|
||||||
std::istringstream iss2(lines[i]);
|
EntityConverter::convertTeleporter(std::vector<std::string> &lines)
|
||||||
// Vector3 position coord0 coord1 coord2
|
{
|
||||||
if ( ! (iss2 >> trash >> trash >>
|
std::vector<std::string> convertedLines;
|
||||||
coords[0] >> coords[1] >> coords[2])) {
|
std::string trash;
|
||||||
std::cerr << "error: Pickup entity requires coordinates" << std::endl;
|
|
||||||
return convertedLines;
|
if ( lines.size() < 2 ) {
|
||||||
}
|
throw std::runtime_error("error: Teleport entity requires at least 2 lines");
|
||||||
havePosition = true;
|
}
|
||||||
|
std::istringstream iss(lines[1]);
|
||||||
|
std::string targetName;
|
||||||
|
// String32 target targetName
|
||||||
|
if ( ! (iss >> trash >> trash >> targetName) ) {
|
||||||
|
throw std::runtime_error( "error: Teleport entity requires target name" );
|
||||||
|
}
|
||||||
|
|
||||||
|
convertedLines.push_back ( "\"classname\" \"trigger_teleport\"\n" );
|
||||||
|
std::stringstream oss;
|
||||||
|
oss << "\"target\" \"" << targetName << std::endl;
|
||||||
|
convertedLines.push_back ( oss.str() );
|
||||||
|
return convertedLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string>
|
||||||
|
EntityConverter::convertTarget(std::vector<std::string> &lines)
|
||||||
|
{
|
||||||
|
std::vector<std::string> convertedLines;
|
||||||
|
std::string coords[3];
|
||||||
|
std::string trash;
|
||||||
|
|
||||||
|
if ( lines.size() < 3 ) {
|
||||||
|
throw std::runtime_error("error: Target entity requires at least 3 lines");
|
||||||
|
}
|
||||||
|
//position and name required, angles optional
|
||||||
|
std::string targetName;
|
||||||
|
std::string angle;
|
||||||
|
bool havePosition = false;
|
||||||
|
bool haveName = false;
|
||||||
|
bool haveAngle = false;
|
||||||
|
|
||||||
|
for (int i = 1; i < lines.size(); i++) {
|
||||||
|
std::string type = getAttributeType(lines[i]);
|
||||||
|
if ( type == "position" ) {
|
||||||
|
std::istringstream iss(lines[i]);
|
||||||
|
// Vector3 position coord0 coord1 coord2
|
||||||
|
if ( ! (iss >> trash >> trash >>
|
||||||
|
coords[0] >> coords[1] >> coords[2])) {
|
||||||
|
throw std::runtime_error( "error: Target entity requires coordinates" );
|
||||||
}
|
}
|
||||||
else if ( type == "pickupType" ) {
|
havePosition = true;
|
||||||
std::istringstream iss2(lines[i]);
|
}
|
||||||
// UInt8 pickupType ID
|
else if ( type == "name" ) {
|
||||||
if ( ! (iss2 >> trash >> trash >> pickupID) ) {
|
std::istringstream iss(lines[i]);
|
||||||
std::cerr << "error: Pickup entity requires pickup ID" << std::endl;
|
// UInt8 name uniqueName
|
||||||
return convertedLines;
|
if ( ! (iss >> trash >> trash >> targetName) ) {
|
||||||
}
|
throw std::runtime_error( "error: Target entity requires target name" );
|
||||||
havePickupID = true;
|
|
||||||
}
|
}
|
||||||
|
haveName = true;
|
||||||
|
}
|
||||||
|
else if ( type == "angles" ) {
|
||||||
|
std::istringstream iss2(lines[i]);
|
||||||
|
// Vector3 angles angle notapplicable notapplicable
|
||||||
|
if ( ! (iss2 >> trash >> trash >> angle) ) {
|
||||||
|
throw std::runtime_error( "error: Target entity requires target angle if specified" );
|
||||||
|
}
|
||||||
|
haveAngle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( havePosition && havePickupID ) {
|
|
||||||
std::stringstream oss;
|
|
||||||
oss << "\"classname\" \"" << pickupMapping_[pickupID] << "\"" << std::endl;
|
|
||||||
convertedLines.push_back ( oss.str() );
|
|
||||||
// coordinates reordered to x, z, y
|
|
||||||
std::stringstream oss2;
|
|
||||||
oss2 << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
|
|
||||||
coords[1] << "\"" << std::endl;
|
|
||||||
convertedLines.push_back ( oss2.str() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ( type == "PlayerSpawn" ) { ///PLAYER SPAWN
|
|
||||||
//minimum of 3 lines, max of ? lines
|
|
||||||
std::istringstream iss2(lines[1]);
|
|
||||||
}
|
|
||||||
else if ( type == "JumpPad" ) { ///JUMP PAD
|
|
||||||
if ( lines.size() < 2 ) {
|
|
||||||
std::cerr << "error: JumpPad entity requires at least 2 lines" << std::endl;
|
|
||||||
}
|
|
||||||
std::istringstream iss2(lines[1]);
|
|
||||||
std::string targetName;
|
|
||||||
// String32 target targetName
|
|
||||||
if ( ! (iss2 >> trash >> trash >> targetName) ) {
|
|
||||||
std::cerr << "error: JumpPad entity requires target name" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
convertedLines.push_back ( "\"classname\" \"trigger_push\"\n" );
|
if ( havePosition && haveName) {
|
||||||
|
//**! no way to tell if teleporter or jump pad dest from targetName alone
|
||||||
|
if ( targetMap_[targetName] == "Teleporter") {
|
||||||
|
convertedLines.push_back ( "\"classname\" \"misc_teleporter_dest\"\n" );
|
||||||
|
}
|
||||||
|
else if ( targetMap_[targetName] == "JumpPad") {
|
||||||
|
convertedLines.push_back ( "\"classname\" \"target_push\"\n" );
|
||||||
|
}
|
||||||
std::stringstream oss;
|
std::stringstream oss;
|
||||||
oss << "\"target\" \"" << targetName << "\"" << std::endl;
|
oss << "\"targetname\" \"" << targetName << "\"\n";
|
||||||
convertedLines.push_back ( oss.str() );
|
convertedLines.push_back ( oss.str() );
|
||||||
}
|
// coordinates reordered to x, z, y
|
||||||
else if ( type == "Teleporter" ) { ///TELEPORTER
|
std::stringstream oss2;
|
||||||
if ( lines.size() < 2 ) {
|
oss2 << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
|
||||||
throw std::runtime_error("error: Teleport entity requires at least 2 lines");
|
coords[1] << "\"" << std::endl;
|
||||||
}
|
convertedLines.push_back ( oss2.str() );
|
||||||
std::istringstream iss2(lines[1]);
|
|
||||||
std::string targetName;
|
|
||||||
// String32 target targetName
|
|
||||||
if ( ! (iss2 >> trash >> trash >> targetName) ) {
|
|
||||||
throw std::runtime_error( "error: Teleport entity requires target name" );
|
|
||||||
}
|
|
||||||
|
|
||||||
convertedLines.push_back ( "\"classname\" \"trigger_teleport\"\n" );
|
// Write angle only if position and name exist
|
||||||
std::stringstream oss;
|
if ( haveAngle ) {
|
||||||
oss << "\"target\" \"" << targetName << std::endl;
|
std::stringstream oss3;
|
||||||
convertedLines.push_back ( oss.str() );
|
oss3 << "\"angle\" \"" << angle << "\"\n";
|
||||||
}
|
convertedLines.push_back (oss3.str() );
|
||||||
else if ( type == "Target" ) { ///TARGET
|
|
||||||
if ( lines.size() < 3 ) {
|
|
||||||
throw std::runtime_error("error: Target entity requires at least 3 lines");
|
|
||||||
}
|
}
|
||||||
//position and name required, angles optional
|
|
||||||
std::string targetName;
|
|
||||||
std::string angle;
|
|
||||||
bool havePosition = false;
|
|
||||||
bool haveName = false;
|
|
||||||
bool haveAngle = false;
|
|
||||||
|
|
||||||
for (int i = 1; i < lines.size(); i++) {
|
|
||||||
type = getAttributeType(lines[i]);
|
|
||||||
if ( type == "position" ) {
|
|
||||||
std::istringstream iss2(lines[i]);
|
|
||||||
// Vector3 position coord0 coord1 coord2
|
|
||||||
if ( ! (iss2 >> trash >> trash >>
|
|
||||||
coords[0] >> coords[1] >> coords[2])) {
|
|
||||||
throw std::runtime_error( "error: Target entity requires coordinates" );
|
|
||||||
}
|
|
||||||
havePosition = true;
|
|
||||||
}
|
|
||||||
else if ( type == "name" ) {
|
|
||||||
std::istringstream iss2(lines[i]);
|
|
||||||
// UInt8 name uniqueName
|
|
||||||
if ( ! (iss2 >> trash >> trash >> targetName) ) {
|
|
||||||
throw std::runtime_error( "error: Target entity requires target name" );
|
|
||||||
}
|
|
||||||
haveName = true;
|
|
||||||
}
|
|
||||||
else if ( type == "angles" ) {
|
|
||||||
std::istringstream iss2(lines[i]);
|
|
||||||
// Vector3 angles angle notapplicable notapplicable
|
|
||||||
if ( ! (iss2 >> trash >> trash >> angle) ) {
|
|
||||||
throw std::runtime_error( "error: Target entity requires target angle if specified" );
|
|
||||||
}
|
|
||||||
haveAngle = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( havePosition && haveName) {
|
|
||||||
//**! no way to tell if teleporter or jump pad dest from targetName alone
|
|
||||||
if ( targetMap_[targetName] == "Teleporter") {
|
|
||||||
convertedLines.push_back ( "\"classname\" \"misc_teleporter_dest\"\n" );
|
|
||||||
}
|
|
||||||
else if ( targetMap_[targetName] == "JumpPad") {
|
|
||||||
convertedLines.push_back ( "\"classname\" \"target_push\"\n" );
|
|
||||||
}
|
|
||||||
std::stringstream oss;
|
|
||||||
oss << "\"targetname\" \"" << targetName << "\"\n";
|
|
||||||
convertedLines.push_back ( oss.str() );
|
|
||||||
// coordinates reordered to x, z, y
|
|
||||||
std::stringstream oss2;
|
|
||||||
oss2 << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
|
|
||||||
coords[1] << "\"" << std::endl;
|
|
||||||
convertedLines.push_back ( oss2.str() );
|
|
||||||
|
|
||||||
// Write angle only if position and name exist
|
|
||||||
if ( haveAngle ) {
|
|
||||||
std::stringstream oss3;
|
|
||||||
oss3 << "\"angle\" \"" << angle << "\"\n";
|
|
||||||
convertedLines.push_back (oss3.str() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( type == "Effect" ) { ///EFFECT
|
|
||||||
// to be implemented
|
|
||||||
}
|
|
||||||
else if ( type == "PointLight" ) { ////POINT LIGHT
|
|
||||||
// to be implemented
|
|
||||||
}
|
|
||||||
else if ( type == "Prefab" ) { ////PREFAB
|
|
||||||
// to be implemented?
|
|
||||||
}
|
|
||||||
else if ( type == "CameraPath" ) { ///CAMERA PATH
|
|
||||||
// to be implemented?
|
|
||||||
}
|
|
||||||
else if ( type == "WorldSpawn" ) { ///WORLD SPAWN
|
|
||||||
// do nothing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return convertedLines;
|
return convertedLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string>
|
||||||
|
EntityConverter::convertRaceStart(std::vector<std::string> &lines)
|
||||||
|
{
|
||||||
|
std::vector<std::string> convertedLines;
|
||||||
|
|
||||||
|
return convertedLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string>
|
||||||
|
EntityConverter::convertRaceFinish(std::vector<std::string> &lines)
|
||||||
|
{
|
||||||
|
std::vector<std::string> convertedLines;
|
||||||
|
|
||||||
|
return convertedLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
void
|
||||||
|
EntityConverter::printMapping()
|
||||||
|
{
|
||||||
|
std::map<int, std::string>::iterator it;
|
||||||
|
for (it=pickupMapping_.begin(); it!=pickupMapping_.end(); ++it)
|
||||||
|
std::cout << it->first << " => " << it->second << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
void
|
||||||
|
EntityConverter::printTargetSources()
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string>::iterator it;
|
||||||
|
for (it=targetMap_.begin(); it!=targetMap_.end(); ++it)
|
||||||
|
std::cout << it->first << " => " << it->second << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,13 @@
|
|||||||
* Filename: EntityConverter.hpp
|
* Filename: EntityConverter.hpp
|
||||||
*
|
*
|
||||||
* Description: Convert reflex entities to xonotic entities
|
* Description: Convert reflex entities to xonotic entities
|
||||||
|
* - Simple; operates on single entity at a time
|
||||||
|
* - Only context provided is information on what entities are related.
|
||||||
|
* (i.e. a teleport and it's destination) Can get this information
|
||||||
|
* through the pre-scan constructor of the .map file or by providing
|
||||||
|
* a queue of all the entities in the file.
|
||||||
|
* - Throws exceptions upon encountering malformed entities and when
|
||||||
|
* IO errors occur during object instantiation
|
||||||
*
|
*
|
||||||
* Version: 1.0
|
* Version: 1.0
|
||||||
* Created: 05/27/2017 08:21:14 AM
|
* Created: 05/27/2017 08:21:14 AM
|
||||||
@ -19,6 +26,8 @@
|
|||||||
#define ENTITY_CONVERTER_HPP
|
#define ENTITY_CONVERTER_HPP
|
||||||
|
|
||||||
// Reflex Format
|
// Reflex Format
|
||||||
|
// -****While Worldspawn is an entity, an external parser handles
|
||||||
|
// this because it contains all other entities
|
||||||
// -"Pickup" denoted by ID
|
// -"Pickup" denoted by ID
|
||||||
// conventional item and weapon conversion stored in r2x.ent
|
// conventional item and weapon conversion stored in r2x.ent
|
||||||
// -"PlayerSpawn" consists of coordinate (Vector3),
|
// -"PlayerSpawn" consists of coordinate (Vector3),
|
||||||
@ -30,7 +39,9 @@
|
|||||||
// -"Target" stored as a position (Vector3) and
|
// -"Target" stored as a position (Vector3) and
|
||||||
// "name" (String32)
|
// "name" (String32)
|
||||||
// ***Target can be destination of teleports OR jump pads
|
// ***Target can be destination of teleports OR jump pads
|
||||||
// -MORE TO BE ADDED (Effect, liquids etc)
|
// -"RaceStart" stored as a brush
|
||||||
|
// -"RaceFinish" stored as a brush
|
||||||
|
// -MORE TO BE ADDED? (Effect, PointLight, Prefab, CameraPath, liquids)
|
||||||
|
|
||||||
// Xonotic Format
|
// Xonotic Format
|
||||||
// -pickups prefixed by either "item_" or "weapon_"
|
// -pickups prefixed by either "item_" or "weapon_"
|
||||||
@ -55,6 +66,8 @@
|
|||||||
// a coordinate "origin" (vector3),
|
// a coordinate "origin" (vector3),
|
||||||
// an angle "angle" (a single number),
|
// an angle "angle" (a single number),
|
||||||
// a target "targetname"
|
// a target "targetname"
|
||||||
|
// -checkpoints stored as "trigger_race_checkpoint",
|
||||||
|
// a count "cnt", where "cnt" "0" is the finish line (start line?)
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -63,14 +76,92 @@
|
|||||||
class EntityConverter
|
class EntityConverter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
* Class: EntityConverter
|
||||||
|
* Method: Constructor
|
||||||
|
* Description: Creates entity format mapping
|
||||||
|
* CAUTION: Requires matchRelated 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
|
||||||
|
* THROWS: std::ios::failure on IO failure
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
EntityConverter(std::string entityMapFile);
|
||||||
|
/*
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
* Class: EntityConverter
|
||||||
|
* Method: Constructor
|
||||||
|
* Description: Creates entity format mapping and pre-scans for related entities
|
||||||
|
* Parameter: string entityMapFile, file maps source to target entity formats
|
||||||
|
* Parameter: string reflexMapFile, for pre-scan
|
||||||
|
* THROWS: runtime_error on .ent format error
|
||||||
|
* THROWS: std::ios::failure on IO failure
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
EntityConverter(std::string entityMapFile, std::string reflexMapFile);
|
EntityConverter(std::string entityMapFile, std::string reflexMapFile);
|
||||||
|
/*
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
* Class: EntityConverter
|
||||||
|
* Method: EntityConverter :: convert
|
||||||
|
* Description: Converts a single entity from reflex to xonotic format
|
||||||
|
* Parameter: vector of strings "lines", lines that comprise a single entity
|
||||||
|
* Return: vector of strings, single entity in the converted format
|
||||||
|
* THROWS: runtime_error on malformed .map file
|
||||||
|
* THROWS: runtime_error when called before related entitios are matched
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
std::vector<std::string> convert(std::vector<std::string> lines);
|
std::vector<std::string> convert(std::vector<std::string> lines);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
* Class: EntityConverter
|
||||||
|
* Method: EntityConverter :: getAttributeType
|
||||||
|
* Description: Extracts the type from a line
|
||||||
|
* Parameter: string "line", entity keyword followed by the type
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
std::string getAttributeType(std::string line);
|
std::string getAttributeType(std::string line);
|
||||||
|
/*
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
* Class: EntityConverter
|
||||||
|
* Method: EntityConverter :: mapEntities
|
||||||
|
* Description: Prepare pickupMapping_
|
||||||
|
* Parameter: string mapFile, filename of pickup mapping
|
||||||
|
* Return: true if no error, false if error
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
void mapEntities(std::string mapFile);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
* Class: EntityConverter
|
||||||
|
* Method: EntityConverter :: convert~EntityName~
|
||||||
|
* Description: Multiple methods to convert entity from reflex to xonotic format
|
||||||
|
* Parameter: vector of strings entity, multi-lined entity
|
||||||
|
* Return: vector of strings, the converted entity
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
std::vector<std::string> convertPickup(std::vector<std::string> &entity);
|
||||||
|
std::vector<std::string> convertPlayerSpawn(std::vector<std::string> &entity);
|
||||||
|
std::vector<std::string> convertJumpPad(std::vector<std::string> &entity);
|
||||||
|
std::vector<std::string> convertTeleporter(std::vector<std::string> &entity);
|
||||||
|
std::vector<std::string> convertTarget(std::vector<std::string> &entity);
|
||||||
|
std::vector<std::string> convertRaceStart(std::vector<std::string> &entity);
|
||||||
|
std::vector<std::string> convertRaceFinish(std::vector<std::string> &entity);
|
||||||
|
|
||||||
void printMapping(); //DEBUG
|
void printMapping(); //DEBUG
|
||||||
void printTargetSources(); //DEBUG
|
void printTargetSources(); //DEBUG
|
||||||
|
|
||||||
|
// Related entities must be matched prior to entity conversion
|
||||||
|
bool areEntitiesMatched_;
|
||||||
// Map Reflex pickup IDs to Xonotic pickup identifiers
|
// Map Reflex pickup IDs to Xonotic pickup identifiers
|
||||||
std::map<int, std::string> pickupMapping_;
|
std::map<int, std::string> pickupMapping_;
|
||||||
// Map targets (by name) to their source type
|
// Map targets (by name) to their source type
|
||||||
|
1
ReflexToQ3/includes/cxxopts
Submodule
1
ReflexToQ3/includes/cxxopts
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 11faadeba77d05a80c751e97142875c4b296fa87
|
@ -8,7 +8,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <cxxopts.hpp>
|
#include "cxxopts.hpp"
|
||||||
|
|
||||||
#include "oopless-parser.hpp"
|
#include "oopless-parser.hpp"
|
||||||
#include "brushdef.hpp"
|
#include "brushdef.hpp"
|
||||||
|
Loading…
Reference in New Issue
Block a user