Added entity converter, need integration
This commit is contained in:
parent
df350ac0d0
commit
717be4c3a8
@ -1,14 +1,15 @@
|
||||
EX=reflex2q3
|
||||
CC=g++
|
||||
CFLAGS=-std=c++11 -I"includes" -I"/usr/include/eigen3"
|
||||
TESTEX=test/test-parser
|
||||
|
||||
all: main test
|
||||
|
||||
main: planes.o brushdef.o oopless-parser.o
|
||||
main: planes.o brushdef.o oopless-parser.o EntityConverter.o
|
||||
$(CC) $^ main.cpp $(CFLAGS) -o $(EX) 2>error8.log
|
||||
|
||||
test: planes.o brushdef.o oopless-parser.o test-parser.o
|
||||
$(CC) $^ $(CFLAGS) -o test/test-parser
|
||||
$(CC) $^ $(CFLAGS) -o $(TESTEX)
|
||||
|
||||
test-parser.o: test/test-parser.cpp
|
||||
$(CC) -c $^ $(CFLAGS)
|
||||
@ -21,3 +22,10 @@ brushdef.o: includes/brushdef.cpp
|
||||
|
||||
planes.o: includes/planes.cpp
|
||||
$(CC) -c $^ $(CFLAGS)
|
||||
|
||||
EntityConverter.o: includes/EntityConverter.cpp
|
||||
$(CC) -c $^ $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm *.o *.log $(EX) $(TESTEX)
|
||||
|
||||
|
254
ReflexToQ3/includes/EntityConverter.cpp
Normal file
254
ReflexToQ3/includes/EntityConverter.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: EntityConverter.cpp
|
||||
*
|
||||
* Description: Convert Reflex entities into Xonotic entities
|
||||
*
|
||||
* Version: 0.1
|
||||
* Created: 06/05/2017 07:15:25 PM
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: suhrke@teknik.io
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include "EntityConverter.hpp"
|
||||
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
|
||||
EntityConverter::EntityConverter(std::string entityMapFile)
|
||||
{
|
||||
//Open .ent mapping file
|
||||
std::ifstream fin;
|
||||
fin.open(entityMapFile);
|
||||
|
||||
if ( ! fin.is_open() ) {
|
||||
throw std::ios::failure( "Error opening .ent file" );
|
||||
}
|
||||
|
||||
//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) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string EntityConverter::getAttributeType(std::string line)
|
||||
{
|
||||
std::string type;
|
||||
std::string dataType;
|
||||
std::istringstream iss(line);
|
||||
if ( ! (iss >> dataType >> type )) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<std::string> EntityConverter::convert(std::vector<std::string> lines)
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
std::string coords[3];
|
||||
std::string attribute;
|
||||
std::string trash; //unused tokens
|
||||
|
||||
std::string type;
|
||||
if ( lines.size() < 1 ) {
|
||||
std::cerr << "error: empty entity cannot be converted" << std::endl;
|
||||
return convertedLines;
|
||||
}
|
||||
// second token is the type
|
||||
std::istringstream iss(lines[0]);
|
||||
if ( ! (iss >> trash >> type)) {
|
||||
std::cerr << "error: type is required" << std::endl;
|
||||
return convertedLines;
|
||||
}
|
||||
|
||||
if ( type == "Pickup" ) { ////PICKUP
|
||||
if ( lines.size() < 3 ) {
|
||||
std::cerr << "error: Pickup entity requires at least 3 lines" << std::endl;
|
||||
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::istringstream iss2(lines[i]);
|
||||
// Vector3 position coord0 coord1 coord2
|
||||
if ( ! (iss2 >> trash >> trash >>
|
||||
coords[0] >> coords[1] >> coords[2])) {
|
||||
std::cerr << "error: Pickup entity requires coordinates" << std::endl;
|
||||
return convertedLines;
|
||||
}
|
||||
havePosition = true;
|
||||
}
|
||||
else if ( type == "pickupType" ) {
|
||||
std::istringstream iss2(lines[i]);
|
||||
// UInt8 pickupType ID
|
||||
if ( ! (iss2 >> trash >> trash >> pickupID) ) {
|
||||
std::cerr << "error: Pickup entity requires pickup ID" << std::endl;
|
||||
return convertedLines;
|
||||
}
|
||||
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() );
|
||||
}
|
||||
}
|
||||
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" );
|
||||
std::stringstream oss;
|
||||
oss << "\"target\" \"" << targetName << std::endl;
|
||||
convertedLines.push_back ( oss.str() );
|
||||
}
|
||||
else if ( type == "Teleporter" ) { ///TELEPORTER
|
||||
/* if ( lines.size() < 2 ) {
|
||||
throw std::runtime_error("error: Teleport entity requires at least 2 lines");
|
||||
}
|
||||
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" );
|
||||
std::stringstream oss;
|
||||
oss << "\"target\" \"" << targetName << std::endl;
|
||||
convertedLines.push_back ( oss.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
|
||||
convertedLines.push_back ( "\"classname\" \"misc_teleporter_dest\"\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;
|
||||
}
|
76
ReflexToQ3/includes/EntityConverter.hpp
Normal file
76
ReflexToQ3/includes/EntityConverter.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: EntityConverter.hpp
|
||||
*
|
||||
* Description: Convert reflex entities to xonotic entities
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 05/27/2017 08:21:14 AM
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: suhrke@teknik.io
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#ifndef ENTITY_CONVERTER_HPP
|
||||
#define ENTITY_CONVERTER_HPP
|
||||
|
||||
// Reflex Format
|
||||
// -"Pickup" denoted by ID
|
||||
// conventional item and weapon conversion stored in r2x.ent
|
||||
// -"PlayerSpawn" consists of coordinate (Vector3),
|
||||
// angle (first element of Vector3),
|
||||
// team indicator (on individual lines),
|
||||
// game type indicator (on individual lines)
|
||||
// -"JumpPad" stored as a brush and a Target
|
||||
// -"Teleporter" stored as a brush and a Target
|
||||
// -"Target" stored as a position (Vector3) and
|
||||
// "name" (String32)
|
||||
// ***Target can be destination of teleports OR jump pads
|
||||
// -MORE TO BE ADDED (Effect, liquids etc)
|
||||
|
||||
// Xonotic Format
|
||||
// -pickups prefixed by either "item_" or "weapon_"
|
||||
// -spawns stored as separate entity types
|
||||
// "info_player_deathmatch"
|
||||
// "info_player_team1"
|
||||
// "info_player_team2"
|
||||
// "info_player_team3"
|
||||
// "info_player_team4"
|
||||
// where each consists of a coordinate "origin" (vector3)
|
||||
// an angle "angle" (a single number)
|
||||
// -jump pads stored as "classname" "target_push",
|
||||
// a coordinate "origin" (vector3),
|
||||
// a target "targetname"
|
||||
// OR stored as "classname" "trigger_push",
|
||||
// a target "target",
|
||||
// a brush
|
||||
// -teleports stored as "classname" "trigger_teleport"
|
||||
// a target "target",
|
||||
// a brush
|
||||
// -teleport destinations stored as "classname" "misc_teleporter_dest",
|
||||
// a coordinate "origin" (vector3),
|
||||
// an angle "angle" (a single number),
|
||||
// a target "targetname"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class EntityConverter
|
||||
{
|
||||
public:
|
||||
EntityConverter(std::string entityMapFile);
|
||||
std::vector<std::string> convert(std::vector<std::string> lines);
|
||||
void printMapping(); //DEBUG
|
||||
protected:
|
||||
private:
|
||||
std::string getAttributeType(std::string line);
|
||||
std::map<int, std::string> pickupMapping;
|
||||
};
|
||||
|
||||
#endif //ENTITY_CONVERTER_HPP
|
||||
|
25
ReflexToQ3/r2x.ent
Normal file
25
ReflexToQ3/r2x.ent
Normal file
@ -0,0 +1,25 @@
|
||||
40 item_health_small
|
||||
41 item_health_medium
|
||||
42 item_health_large
|
||||
43 item_health_mega
|
||||
50 item_armor_small
|
||||
51 item_armor_medium
|
||||
52 item_armor_large
|
||||
53 item_armor_big
|
||||
1 weapon_uzi
|
||||
2 weapon_grenadelauncher
|
||||
3 weapon_hagar
|
||||
4 weapon_rocketlauncher
|
||||
5 weapon_electro
|
||||
6 weapon_nex
|
||||
20 burst
|
||||
21 item_shells
|
||||
22 item_rockets
|
||||
23 item_cells
|
||||
24 item_rockets
|
||||
25 item_bullets
|
||||
26 item_cells
|
||||
60 item_strength
|
||||
62 item_invincible
|
||||
70 item_flag_team1
|
||||
71 item_flag_team2
|
Loading…
Reference in New Issue
Block a user