2014-02-07 15:20:34 +01:00
|
|
|
|
/////////////////////////////////////
|
|
|
|
|
// Created by Pontus Fransson 2013 //
|
|
|
|
|
/////////////////////////////////////
|
|
|
|
|
|
2014-01-24 09:00:59 +01:00
|
|
|
|
#include "LevelParser.h"
|
|
|
|
|
|
2014-01-27 10:14:02 +01:00
|
|
|
|
#include "Loader.h"
|
2014-01-27 13:57:18 +01:00
|
|
|
|
#include "ParseFunctions.h"
|
2014-01-27 10:14:02 +01:00
|
|
|
|
|
2014-01-24 10:01:58 +01:00
|
|
|
|
using namespace GameLogic;
|
2014-01-24 10:42:19 +01:00
|
|
|
|
using namespace ::LevelFileLoader;
|
2014-02-03 14:50:15 +01:00
|
|
|
|
using namespace Utility::DynamicMemory;
|
2014-01-24 10:01:58 +01:00
|
|
|
|
|
|
|
|
|
LevelParser::LevelParser()
|
|
|
|
|
{
|
2014-02-10 16:24:05 +01:00
|
|
|
|
formatVersion.formatVersionMajor = 3;
|
2014-01-28 11:27:29 +01:00
|
|
|
|
formatVersion.formatVersionMinor = 0;
|
2014-01-24 10:01:58 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LevelParser::~LevelParser()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-03 14:50:15 +01:00
|
|
|
|
std::vector<SmartPointer<ObjectTypeHeader>> LevelParser::Parse(std::string filename)
|
2014-01-24 10:01:58 +01:00
|
|
|
|
{
|
2014-01-28 11:27:29 +01:00
|
|
|
|
int bufferSize = 0;
|
2014-01-28 16:15:10 +01:00
|
|
|
|
int counter = 0;
|
2014-02-12 14:48:58 +01:00
|
|
|
|
bool loadCgf;
|
2014-01-28 11:27:29 +01:00
|
|
|
|
|
2014-02-03 14:50:15 +01:00
|
|
|
|
std::vector<SmartPointer<ObjectTypeHeader>> objects;
|
2014-01-28 11:27:29 +01:00
|
|
|
|
|
2014-01-24 10:01:58 +01:00
|
|
|
|
//Read entire level file.
|
2014-01-27 10:14:02 +01:00
|
|
|
|
Loader loader;
|
2014-01-28 16:15:10 +01:00
|
|
|
|
char* buffer = (char*)loader.LoadFile(filename.c_str(), bufferSize);
|
2014-01-24 10:01:58 +01:00
|
|
|
|
|
2014-01-28 11:27:29 +01:00
|
|
|
|
//Read format version
|
2014-02-07 14:12:54 +01:00
|
|
|
|
LevelLoaderInternal::FormatVersion levelFormatVersion;
|
2014-02-04 11:36:10 +01:00
|
|
|
|
ParseObject(&buffer[counter], &levelFormatVersion, sizeof(levelFormatVersion));
|
|
|
|
|
counter += sizeof(levelFormatVersion);
|
2014-01-28 11:27:29 +01:00
|
|
|
|
if(this->formatVersion != levelFormatVersion)
|
|
|
|
|
{
|
2014-02-07 14:12:54 +01:00
|
|
|
|
//Returns an empty vector, because it will most likely fail to read the level format.
|
|
|
|
|
return objects;
|
2014-01-28 11:27:29 +01:00
|
|
|
|
}
|
2014-01-24 10:01:58 +01:00
|
|
|
|
|
2014-02-04 11:36:10 +01:00
|
|
|
|
while(counter < bufferSize)
|
2014-01-24 10:01:58 +01:00
|
|
|
|
{
|
2014-02-12 14:48:58 +01:00
|
|
|
|
loadCgf = true;
|
2014-01-24 10:01:58 +01:00
|
|
|
|
//Get typeID
|
2014-02-07 14:44:25 +01:00
|
|
|
|
ObjectType typeID;
|
2014-01-28 16:15:10 +01:00
|
|
|
|
ParseObject(&buffer[counter], &typeID, sizeof(typeID));
|
2014-02-07 14:44:25 +01:00
|
|
|
|
switch((int)typeID)
|
2014-01-24 10:01:58 +01:00
|
|
|
|
{
|
2014-02-03 14:50:15 +01:00
|
|
|
|
case ObjectType_LevelMetaData:
|
|
|
|
|
{
|
2014-02-07 14:44:25 +01:00
|
|
|
|
SmartPointer<ObjectTypeHeader> header = new LevelMetaData;
|
|
|
|
|
ParseLevelMetaData(&buffer[counter], *(LevelMetaData*)header.Get(), counter);
|
2014-02-03 14:50:15 +01:00
|
|
|
|
objects.push_back(header);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-01-24 10:01:58 +01:00
|
|
|
|
|
2014-02-07 14:12:54 +01:00
|
|
|
|
//This is by design, static and dynamic is using the same converter. Do not add anything inbetween them.
|
|
|
|
|
//Unless they are changed to not be the same.
|
2014-02-03 14:50:15 +01:00
|
|
|
|
case ObjectType_Static: case ObjectType_Dynamic:
|
|
|
|
|
{
|
2014-02-07 14:12:54 +01:00
|
|
|
|
//Get specialType.
|
|
|
|
|
ObjectSpecialType specialType;
|
|
|
|
|
ParseObject(&buffer[counter+4], &specialType, sizeof(typeID));
|
|
|
|
|
|
|
|
|
|
switch(specialType)
|
|
|
|
|
{
|
2014-02-12 14:48:58 +01:00
|
|
|
|
//there is no difference when parsing these specialTypes.
|
|
|
|
|
case ObjectSpecialType_CrystalShard:
|
|
|
|
|
case ObjectSpecialType_CrystalFormation:
|
|
|
|
|
case ObjectSpecialType_Spike:
|
|
|
|
|
case ObjectSpecialType_SpikeBox:
|
|
|
|
|
case ObjectSpecialType_RedExplosiveBox:
|
|
|
|
|
case ObjectSpecialType_StandarsBox:
|
|
|
|
|
case ObjectSpecialType_Stone:
|
2014-02-07 14:12:54 +01:00
|
|
|
|
case ObjectSpecialType_Building:
|
|
|
|
|
{
|
|
|
|
|
ObjectHeader* header = new ObjectHeader;
|
2014-02-12 14:48:58 +01:00
|
|
|
|
ParseObject(&buffer[counter], *header, counter, loadCgf);
|
2014-02-07 14:12:54 +01:00
|
|
|
|
objects.push_back(header);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-02-12 14:48:58 +01:00
|
|
|
|
|
2014-02-07 14:12:54 +01:00
|
|
|
|
case ObjectSpecialType_JumpPad:
|
|
|
|
|
{
|
|
|
|
|
JumpPadAttributes* header = new JumpPadAttributes;
|
2014-02-12 14:48:58 +01:00
|
|
|
|
ParseObject(&buffer[counter], *header, counter, loadCgf);
|
2014-02-07 14:12:54 +01:00
|
|
|
|
|
|
|
|
|
//Read the spec
|
|
|
|
|
ParseObject(&buffer[counter], header->direction, 16);
|
2014-02-12 14:48:58 +01:00
|
|
|
|
counter += 16;
|
2014-02-07 14:12:54 +01:00
|
|
|
|
objects.push_back(header);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-02-12 14:48:58 +01:00
|
|
|
|
|
2014-02-07 14:12:54 +01:00
|
|
|
|
case ObjectSpecialType_Portal:
|
|
|
|
|
{
|
|
|
|
|
PortalAttributes* header = new PortalAttributes;
|
2014-02-12 14:48:58 +01:00
|
|
|
|
ParseObject(&buffer[counter], *header, counter, loadCgf);
|
2014-02-07 14:12:54 +01:00
|
|
|
|
|
|
|
|
|
ParseObject(&buffer[counter], header->destination, 12);
|
2014-02-12 14:48:58 +01:00
|
|
|
|
counter += 12;
|
2014-02-07 14:12:54 +01:00
|
|
|
|
objects.push_back(header);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-02-10 16:24:05 +01:00
|
|
|
|
|
|
|
|
|
case ObjectSpecialType_World:
|
2014-02-07 14:12:54 +01:00
|
|
|
|
{
|
2014-02-10 16:24:05 +01:00
|
|
|
|
WorldAttributes* header = new WorldAttributes;
|
2014-02-12 14:48:58 +01:00
|
|
|
|
ParseObject(&buffer[counter], *header, counter, loadCgf);
|
2014-02-07 14:12:54 +01:00
|
|
|
|
|
2014-02-10 16:24:05 +01:00
|
|
|
|
ParseObject(&buffer[counter], &header->worldSize, 8);
|
2014-02-12 14:48:58 +01:00
|
|
|
|
counter += 8;
|
2014-02-07 14:12:54 +01:00
|
|
|
|
objects.push_back(header);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-02-10 14:58:39 +01:00
|
|
|
|
|
2014-02-10 16:24:05 +01:00
|
|
|
|
case ObjectSpecialType_Sky:
|
|
|
|
|
{
|
2014-02-12 14:48:58 +01:00
|
|
|
|
loadCgf = false;
|
2014-02-10 16:24:05 +01:00
|
|
|
|
SkyAttributes* header = new SkyAttributes;
|
2014-02-12 14:48:58 +01:00
|
|
|
|
ParseObject(&buffer[counter], *header, counter, loadCgf);
|
2014-02-10 16:24:05 +01:00
|
|
|
|
|
|
|
|
|
ParseObject(&buffer[counter], &header->skySize, 4);
|
2014-02-12 14:48:58 +01:00
|
|
|
|
counter += 4;
|
2014-02-10 16:24:05 +01:00
|
|
|
|
objects.push_back(header);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-02-12 14:48:58 +01:00
|
|
|
|
|
|
|
|
|
case ObjectSpecialType_SpawnPoint:
|
|
|
|
|
{
|
|
|
|
|
loadCgf = false;
|
|
|
|
|
ObjectHeader* header = new ObjectHeader;
|
|
|
|
|
ParseObject(&buffer[counter], *header, counter, loadCgf);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-07 14:12:54 +01:00
|
|
|
|
default:
|
|
|
|
|
//Couldn't find specialType
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-02-03 14:50:15 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
2014-01-28 16:15:10 +01:00
|
|
|
|
|
2014-02-03 14:50:15 +01:00
|
|
|
|
case ObjectType_Light:
|
|
|
|
|
{
|
|
|
|
|
LightType lightType;
|
|
|
|
|
|
|
|
|
|
//Get Light type
|
|
|
|
|
ParseObject(&buffer[counter+4], &lightType, sizeof(lightType));
|
|
|
|
|
|
2014-02-07 14:12:54 +01:00
|
|
|
|
//We only support PointLight for now.
|
|
|
|
|
BasicLight* header = new BasicLight;
|
|
|
|
|
ParseObject(&buffer[counter], header, sizeof(*header));
|
|
|
|
|
counter += sizeof(*header);
|
|
|
|
|
objects.push_back(header);
|
|
|
|
|
/*switch(lightType)
|
2014-02-03 14:50:15 +01:00
|
|
|
|
{
|
|
|
|
|
case LightType_PointLight:
|
|
|
|
|
{
|
|
|
|
|
PointLight* header = new PointLight;
|
|
|
|
|
ParseObject(&buffer[counter], header, sizeof(*header));
|
|
|
|
|
counter += sizeof(*header);
|
|
|
|
|
objects.push_back(header);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case LightType_DirectionalLight:
|
|
|
|
|
{
|
|
|
|
|
DirectionalLight* header = new DirectionalLight;
|
|
|
|
|
ParseObject(&buffer[counter], header, sizeof(*header));
|
|
|
|
|
counter += sizeof(*header);
|
|
|
|
|
objects.push_back(header);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case LightType_SpotLight:
|
|
|
|
|
{
|
|
|
|
|
SpotLight* header = new SpotLight;
|
|
|
|
|
ParseObject(&buffer[counter], header, sizeof(*header));
|
|
|
|
|
counter += sizeof(*header);
|
|
|
|
|
objects.push_back(header);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
//Undefined LightType.
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-02-07 14:12:54 +01:00
|
|
|
|
break;*/
|
2014-02-03 14:50:15 +01:00
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
//Couldn't find typeID. FAIL!!!!!!
|
|
|
|
|
break;
|
2014-01-24 10:01:58 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return objects;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-28 11:27:29 +01:00
|
|
|
|
//f<>r meta information om leveln.
|
|
|
|
|
LevelMetaData LevelParser::ParseHeader(std::string filename)
|
2014-01-24 10:01:58 +01:00
|
|
|
|
{
|
2014-01-28 11:27:29 +01:00
|
|
|
|
int bufferSize = 0;
|
2014-01-28 16:15:10 +01:00
|
|
|
|
int counter = 0;
|
2014-01-28 11:27:29 +01:00
|
|
|
|
|
|
|
|
|
LevelMetaData levelHeader;
|
|
|
|
|
levelHeader.typeID = ObjectType::ObjectType_Unknown;
|
|
|
|
|
|
2014-01-24 10:01:58 +01:00
|
|
|
|
//Read entire level file.
|
2014-01-27 10:14:02 +01:00
|
|
|
|
Loader loader;
|
2014-01-28 16:15:10 +01:00
|
|
|
|
char* buffer = (char*)loader.LoadFile(filename.c_str(), bufferSize);
|
2014-01-24 10:01:58 +01:00
|
|
|
|
|
2014-01-28 11:27:29 +01:00
|
|
|
|
//Read format version
|
2014-02-07 14:12:54 +01:00
|
|
|
|
LevelLoaderInternal::FormatVersion levelFormatVersion;
|
2014-02-04 11:36:10 +01:00
|
|
|
|
ParseObject(&buffer[counter], &levelFormatVersion, sizeof(formatVersion));
|
|
|
|
|
counter += sizeof(levelFormatVersion);
|
2014-01-28 11:27:29 +01:00
|
|
|
|
if(this->formatVersion != levelFormatVersion)
|
|
|
|
|
{
|
|
|
|
|
//Do something if it's not the same version
|
2014-02-07 14:12:54 +01:00
|
|
|
|
|
|
|
|
|
//Returns an empty levelHeader with ObjectType_Unknown.
|
|
|
|
|
//Because it will not be able to read another version of the level format.
|
|
|
|
|
return levelHeader;
|
2014-01-28 11:27:29 +01:00
|
|
|
|
}
|
2014-01-24 10:01:58 +01:00
|
|
|
|
|
2014-01-28 11:27:29 +01:00
|
|
|
|
//Find the header in the returned string.
|
|
|
|
|
while(counter < bufferSize)
|
2014-01-24 10:01:58 +01:00
|
|
|
|
{
|
2014-02-07 15:20:34 +01:00
|
|
|
|
ObjectType typeID;
|
2014-01-28 16:15:10 +01:00
|
|
|
|
ParseObject(&buffer[counter], &typeID, sizeof(typeID));
|
2014-01-28 11:27:29 +01:00
|
|
|
|
|
2014-02-07 15:20:34 +01:00
|
|
|
|
switch(typeID)
|
2014-01-24 10:01:58 +01:00
|
|
|
|
{
|
2014-01-28 11:27:29 +01:00
|
|
|
|
case ObjectType_LevelMetaData:
|
2014-01-28 16:15:10 +01:00
|
|
|
|
ParseLevelMetaData(&buffer[counter], levelHeader, counter);
|
2014-01-28 11:27:29 +01:00
|
|
|
|
return levelHeader;
|
2014-01-24 10:01:58 +01:00
|
|
|
|
break;
|
2014-02-04 11:36:10 +01:00
|
|
|
|
|
|
|
|
|
//This is by design, static and dynamic is using the same converter. Do not add anything inbetween them.
|
|
|
|
|
case ObjectType_Static: case ObjectType_Dynamic:
|
|
|
|
|
{
|
|
|
|
|
ObjectHeader header;
|
2014-02-12 14:48:58 +01:00
|
|
|
|
ParseObject(&buffer[counter], &header, counter);
|
2014-02-07 15:20:34 +01:00
|
|
|
|
|
|
|
|
|
switch(header.specialTypeID)
|
|
|
|
|
{
|
|
|
|
|
case ObjectSpecialType_JumpPad:
|
|
|
|
|
counter += sizeof(16);
|
|
|
|
|
break;
|
|
|
|
|
case ObjectSpecialType_Portal:
|
|
|
|
|
counter += sizeof(12);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-01-24 10:01:58 +01:00
|
|
|
|
break;
|
2014-02-04 11:36:10 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ObjectType_Light:
|
|
|
|
|
{
|
|
|
|
|
LightType lightType;
|
|
|
|
|
ParseObject(&buffer[counter+4], &lightType, sizeof(lightType));
|
|
|
|
|
|
2014-02-07 14:12:54 +01:00
|
|
|
|
//We only support pointlight for now.
|
|
|
|
|
counter += sizeof(BasicLight);
|
|
|
|
|
/*
|
2014-02-04 11:36:10 +01:00
|
|
|
|
switch(lightType)
|
|
|
|
|
{
|
|
|
|
|
case LightType_PointLight:
|
|
|
|
|
{
|
|
|
|
|
counter += sizeof(PointLight);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case LightType_DirectionalLight:
|
|
|
|
|
{
|
|
|
|
|
counter += sizeof(DirectionalLight);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case LightType_SpotLight:
|
|
|
|
|
{
|
|
|
|
|
counter += sizeof(SpotLight);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
//Undefined LightType.
|
|
|
|
|
break;
|
2014-02-07 14:12:54 +01:00
|
|
|
|
}*/
|
2014-02-04 11:36:10 +01:00
|
|
|
|
}
|
2014-01-24 10:01:58 +01:00
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
//Couldn't find typeID. FAIL!!!!!!
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-28 11:27:29 +01:00
|
|
|
|
return levelHeader;
|
2014-01-24 10:01:58 +01:00
|
|
|
|
}
|