1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-09 12:22:34 +01:00

Refactor some text data loading to seperate class

This commit is contained in:
Daniel Evans 2014-09-13 03:29:32 +01:00
parent f7398f17f8
commit c3956ac888
4 changed files with 293 additions and 194 deletions

View File

@ -0,0 +1,30 @@
#ifndef _GENERICDATLOADER_HPP_
#define _GENERICDATLOADER_CPP_
#include <map>
#include <memory>
class DynamicObjectData;
typedef std::shared_ptr<DynamicObjectData> DynamicObjectDataPtr;
typedef std::map<std::string,DynamicObjectDataPtr> DynamicObjectDataPtrs;
struct WeaponData;
typedef std::shared_ptr<WeaponData> WeaponDataPtr;
typedef std::map<std::string, WeaponDataPtr> WeaponDataPtrs;
struct VehicleInfo;
typedef std::shared_ptr<VehicleInfo> VehicleInfoPtr;
typedef std::map<std::string, VehicleInfoPtr> VehicleInfoPtrs;
class GenericDATLoader
{
public:
void loadDynamicObjects(const std::string& name, DynamicObjectDataPtrs& data);
void loadWeapons(const std::string& name, WeaponDataPtrs& weaponData);
void loadHandling(const std::string& name, VehicleInfoPtrs& vehicleData);
};
#endif

View File

@ -10,6 +10,7 @@
#include <script/SCMFile.hpp> #include <script/SCMFile.hpp>
#include <render/Model.hpp> #include <render/Model.hpp>
#include <loaders/GenericDATLoader.hpp>
#include <loaders/LoaderGXT.hpp> #include <loaders/LoaderGXT.hpp>
#include <iostream> #include <iostream>
@ -311,62 +312,9 @@ void GameData::loadWeather(const std::string &path)
void GameData::loadHandling(const std::string& path) void GameData::loadHandling(const std::string& path)
{ {
std::ifstream hndFile(path.c_str()); GenericDATLoader l;
if(! hndFile.is_open()) { l.loadHandling(path, vehicleInfo);
std::cerr << "Error loadind handling data " << path << std::endl;
return;
}
std::string lineBuff;
while(std::getline(hndFile, lineBuff)) {
if(lineBuff.at(0) == ';') continue;
std::stringstream ss(lineBuff);
VehicleHandlingInfo info;
ss >> info.ID;
ss >> info.mass;
ss >> info.dimensions.x;
ss >> info.dimensions.y;
ss >> info.dimensions.z;
ss >> info.centerOfMass.x;
ss >> info.centerOfMass.y;
ss >> info.centerOfMass.z;
ss >> info.percentSubmerged;
ss >> info.tractionMulti;
ss >> info.tractionLoss;
ss >> info.tractionBias;
ss >> info.numGears;
ss >> info.maxVelocity;
ss >> info.acceleration;
char dt, et;
ss >> dt; ss >> et;
info.driveType = (VehicleHandlingInfo::DriveType)dt;
info.engineType = (VehicleHandlingInfo::EngineType)et;
ss >> info.brakeDeceleration;
ss >> info.brakeBias;
ss >> info.ABS;
ss >> info.steeringLock;
ss >> info.suspensionForce;
ss >> info.suspensionDamping;
ss >> info.seatOffset;
ss >> info.damageMulti;
ss >> info.value;
ss >> info.suspensionUpperLimit;
ss >> info.suspensionLowerLimit;
ss >> info.suspensionBias;
ss >> std::hex >> info.flags;
auto mit = vehicleInfo.find(info.ID);
if(mit == vehicleInfo.end()) {
vehicleInfo.insert({info.ID,
VehicleInfoHandle(new VehicleInfo{info})});
}
else {
mit->second->handling = info;
}
}
} }
SCMFile *GameData::loadSCM(const std::string &path) SCMFile *GameData::loadSCM(const std::string &path)
@ -510,127 +458,16 @@ void GameData::loadIFP(const std::string &name)
void GameData::loadDynamicObjects(const std::string& name) void GameData::loadDynamicObjects(const std::string& name)
{ {
std::ifstream dfile(name.c_str()); GenericDATLoader l;
if(dfile.is_open()) { l.loadDynamicObjects(name, dynamicObjectData);
std::string lineBuff;
while(std::getline(dfile, lineBuff)) {
if(lineBuff.at(0) == ';') continue;
std::stringstream ss(lineBuff);
std::shared_ptr<DynamicObjectData> dyndata(new DynamicObjectData);
ss >> dyndata->modelName;
auto cpos = dyndata->modelName.find(',');
if( cpos != dyndata->modelName.npos ) {
dyndata->modelName.erase(cpos);
}
ss >> dyndata->mass;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->turnMass;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->airRes;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->elacticity;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->bouancy;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->uprootForce;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->collDamageMulti;
if(ss.peek() == ',') ss.ignore(1);
int tmp;
ss >> tmp;
dyndata->collDamageFlags = tmp;
if(ss.peek() == ',') ss.ignore(1);
ss >> tmp;
dyndata->collResponseFlags = tmp;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->cameraAvoid;
dynamicObjectData.insert({dyndata->modelName, dyndata});
}
}
else {
engine->logError("Failed to load dynamic object file: " + name);
}
} }
void GameData::loadWeaponDAT(const std::string &name) void GameData::loadWeaponDAT(const std::string &name)
{ {
std::ifstream dfile(name.c_str()); GenericDATLoader l;
if(dfile.is_open()) { l.loadWeapons(name, weaponData);
std::string linebuffer;
int slotNum = 0;
while(std::getline(dfile, linebuffer)) {
if(linebuffer[0] == '#') continue;
std::stringstream ss(linebuffer);
std::shared_ptr<WeaponData> data(new WeaponData);
ss >> data->name;
if( data->name == "ENDWEAPONDATA" ) continue;
// Skip lines with blank names (probably an empty line).
if( std::find_if(data->name.begin(), data->name.end(),
::isalnum) == std::end( data->name ) ) {
continue;
}
std::transform(data->name.begin(), data->name.end(),
data->name.begin(), ::tolower);
std::string firetype;
ss >> firetype;
if( firetype == "MELEE" ) {
data->fireType = WeaponData::MELEE;
}
else if( firetype == "INSTANT_HIT" ) {
data->fireType = WeaponData::INSTANT_HIT;
}
else if( firetype == "PROJECTILE" ) {
data->fireType = WeaponData::PROJECTILE;
}
else {
engine->logError("Unkown firetype: " + firetype);
}
ss >> data->hitRange;
ss >> data->fireRate;
ss >> data->reloadMS;
ss >> data->clipSize;
ss >> data->damage;
ss >> data->speed;
ss >> data->meleeRadius;
ss >> data->lifeSpan;
ss >> data->spread;
ss >> data->fireOffset.x;
ss >> data->fireOffset.y;
ss >> data->fireOffset.z;
ss >> data->animation1;
std::transform(data->animation1.begin(), data->animation1.end(),
data->animation1.begin(), ::tolower);
ss >> data->animation2;
std::transform(data->animation2.begin(), data->animation2.end(),
data->animation2.begin(), ::tolower);
ss >> data->animLoopStart;
ss >> data->animLoopEnd;
ss >> data->animFirePoint;
ss >> data->animCrouchFirePoint;
ss >> data->modelID;
ss >> data->flags;
data->inventorySlot = slotNum++;
weaponData[data->name] = data;
}
}
else {
engine->logError("Failed to load weapon data file:" + name);
}
} }
bool GameData::loadAudio(MADStream& music, const std::string &name) bool GameData::loadAudio(MADStream& music, const std::string &name)

View File

@ -0,0 +1,183 @@
#include <loaders/GenericDATLoader.hpp>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <data/ObjectData.hpp>
#include <data/WeaponData.hpp>
#include <objects/VehicleInfo.hpp>
void GenericDATLoader::loadDynamicObjects(const std::string& name, DynamicObjectDataPtrs& data)
{
std::ifstream dfile(name.c_str());
if(dfile.is_open()) {
std::string lineBuff;
while(std::getline(dfile, lineBuff)) {
if(lineBuff.at(0) == ';') continue;
std::stringstream ss(lineBuff);
DynamicObjectDataPtr dyndata(new DynamicObjectData);
ss >> dyndata->modelName;
auto cpos = dyndata->modelName.find(',');
if( cpos != dyndata->modelName.npos ) {
dyndata->modelName.erase(cpos);
}
ss >> dyndata->mass;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->turnMass;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->airRes;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->elacticity;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->bouancy;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->uprootForce;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->collDamageMulti;
if(ss.peek() == ',') ss.ignore(1);
int tmp;
ss >> tmp;
dyndata->collDamageFlags = tmp;
if(ss.peek() == ',') ss.ignore(1);
ss >> tmp;
dyndata->collResponseFlags = tmp;
if(ss.peek() == ',') ss.ignore(1);
ss >> dyndata->cameraAvoid;
data.insert({dyndata->modelName, dyndata});
}
}
}
void GenericDATLoader::loadWeapons(const std::string& name, WeaponDataPtrs& weaponData)
{
std::ifstream dfile(name.c_str());
if(dfile.is_open()) {
std::string linebuffer;
int slotNum = 0;
while(std::getline(dfile, linebuffer)) {
if(linebuffer[0] == '#') continue;
std::stringstream ss(linebuffer);
WeaponDataPtr data(new WeaponData);
ss >> data->name;
if( data->name == "ENDWEAPONDATA" ) continue;
// Skip lines with blank names (probably an empty line).
if( std::find_if(data->name.begin(), data->name.end(),
::isalnum) == std::end( data->name ) ) {
continue;
}
std::transform(data->name.begin(), data->name.end(),
data->name.begin(), ::tolower);
std::string firetype;
ss >> firetype;
if( firetype == "MELEE" ) {
data->fireType = WeaponData::MELEE;
}
else if( firetype == "INSTANT_HIT" ) {
data->fireType = WeaponData::INSTANT_HIT;
}
else if( firetype == "PROJECTILE" ) {
data->fireType = WeaponData::PROJECTILE;
}
ss >> data->hitRange;
ss >> data->fireRate;
ss >> data->reloadMS;
ss >> data->clipSize;
ss >> data->damage;
ss >> data->speed;
ss >> data->meleeRadius;
ss >> data->lifeSpan;
ss >> data->spread;
ss >> data->fireOffset.x;
ss >> data->fireOffset.y;
ss >> data->fireOffset.z;
ss >> data->animation1;
std::transform(data->animation1.begin(), data->animation1.end(),
data->animation1.begin(), ::tolower);
ss >> data->animation2;
std::transform(data->animation2.begin(), data->animation2.end(),
data->animation2.begin(), ::tolower);
ss >> data->animLoopStart;
ss >> data->animLoopEnd;
ss >> data->animFirePoint;
ss >> data->animCrouchFirePoint;
ss >> data->modelID;
ss >> data->flags;
data->inventorySlot = slotNum++;
weaponData[data->name] = data;
}
}
}
void GenericDATLoader::loadHandling(const std::string& name, VehicleInfoPtrs& vehicleData)
{
std::ifstream hndFile(name.c_str());
if(hndFile.is_open())
{
std::string lineBuff;
while(std::getline(hndFile, lineBuff)) {
if(lineBuff.at(0) == ';') continue;
std::stringstream ss(lineBuff);
VehicleHandlingInfo info;
ss >> info.ID;
ss >> info.mass;
ss >> info.dimensions.x;
ss >> info.dimensions.y;
ss >> info.dimensions.z;
ss >> info.centerOfMass.x;
ss >> info.centerOfMass.y;
ss >> info.centerOfMass.z;
ss >> info.percentSubmerged;
ss >> info.tractionMulti;
ss >> info.tractionLoss;
ss >> info.tractionBias;
ss >> info.numGears;
ss >> info.maxVelocity;
ss >> info.acceleration;
char dt, et;
ss >> dt; ss >> et;
info.driveType = (VehicleHandlingInfo::DriveType)dt;
info.engineType = (VehicleHandlingInfo::EngineType)et;
ss >> info.brakeDeceleration;
ss >> info.brakeBias;
ss >> info.ABS;
ss >> info.steeringLock;
ss >> info.suspensionForce;
ss >> info.suspensionDamping;
ss >> info.seatOffset;
ss >> info.damageMulti;
ss >> info.value;
ss >> info.suspensionUpperLimit;
ss >> info.suspensionLowerLimit;
ss >> info.suspensionBias;
ss >> std::hex >> info.flags;
auto mit = vehicleData.find(info.ID);
if(mit == vehicleData.end()) {
vehicleData.insert({info.ID,
VehicleInfoHandle(new VehicleInfo{info})});
}
else {
mit->second->handling = info;
}
}
}
}

View File

@ -1,6 +1,7 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <data/WeaponData.hpp> #include <data/WeaponData.hpp>
#include "test_globals.hpp" #include "test_globals.hpp"
#include <loaders/GenericDATLoader.hpp>
// Tests against loading various data files // Tests against loading various data files
// These tests are bad but so are the interfaces so it cancels out. // These tests are bad but so are the interfaces so it cancels out.
@ -9,11 +10,15 @@ BOOST_AUTO_TEST_SUITE(DataTests)
BOOST_AUTO_TEST_CASE(test_weapon_dat) BOOST_AUTO_TEST_CASE(test_weapon_dat)
{ {
{ GenericDATLoader l;
// Verify data against some known values. WeaponDataPtrs weaponData;
std::shared_ptr<WeaponData> data = Global::get().e->gameData.weaponData["unarmed"];
BOOST_ASSERT( data ); l.loadWeapons(Global::get().getGamePath() + "/data/weapon.dat", weaponData);
BOOST_ASSERT( weaponData.size() > 0 );
BOOST_ASSERT( weaponData.find("unarmed") != weaponData.end() );
WeaponDataPtr data = weaponData["unarmed"];
BOOST_CHECK( data->fireType == WeaponData::MELEE ); BOOST_CHECK( data->fireType == WeaponData::MELEE );
BOOST_CHECK( data->hitRange == 2.8f ); BOOST_CHECK( data->hitRange == 2.8f );
@ -36,6 +41,50 @@ BOOST_AUTO_TEST_CASE(test_weapon_dat)
BOOST_CHECK( data->flags == 0) ; BOOST_CHECK( data->flags == 0) ;
} }
BOOST_AUTO_TEST_CASE(test_dynamic_dat_loader)
{
GenericDATLoader l;
DynamicObjectDataPtrs loaded;
l.loadDynamicObjects(Global::get().getGamePath() + "/data/object.dat", loaded);
BOOST_ASSERT( loaded.size() > 0 );
BOOST_ASSERT( loaded.find("wastebin") != loaded.end() );
BOOST_ASSERT( loaded.find("lamppost1") != loaded.end() );
DynamicObjectDataPtr lamp = loaded["lamppost1"];
BOOST_CHECK_EQUAL( lamp->mass, 600.0);
BOOST_CHECK_EQUAL( lamp->turnMass, 4000.0);
BOOST_CHECK_CLOSE( lamp->airRes, 0.99, 1.0);
BOOST_CHECK_CLOSE( lamp->elacticity, 0.05, 0.01);
BOOST_CHECK_EQUAL( lamp->bouancy, 50.0);
BOOST_CHECK_EQUAL( lamp->uprootForce, 400);
BOOST_CHECK_EQUAL( lamp->collDamageMulti, 1.0);
BOOST_CHECK_EQUAL( lamp->collDamageFlags, 1);
BOOST_CHECK_EQUAL( lamp->collResponseFlags, 1);
BOOST_CHECK_EQUAL( lamp->cameraAvoid, false);
}
BOOST_AUTO_TEST_CASE(test_handling_data_loader)
{
GenericDATLoader l;
VehicleInfoPtrs loaded;
l.loadHandling(Global::get().getGamePath() + "/data/handling.cfg", loaded);
BOOST_ASSERT( loaded.size() > 0 );
BOOST_ASSERT( loaded.find("STINGER") != loaded.end() );
VehicleInfoPtr info = loaded["STINGER"];
VehicleHandlingInfo& handling = info->handling;
BOOST_CHECK_EQUAL( handling.mass, 1000.0 );
BOOST_CHECK_EQUAL( handling.flags, 0xA182 );
BOOST_CHECK_EQUAL( handling.driveType, VehicleHandlingInfo::All );
BOOST_CHECK_EQUAL( handling.engineType, VehicleHandlingInfo::Petrol );
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()