[IMapEnts] Correct map entities

This commit is contained in:
momo5502 2017-03-25 22:18:31 +01:00
parent c77cbf39b2
commit 654b2210ce
6 changed files with 219 additions and 5 deletions

View File

@ -8,7 +8,7 @@ namespace Assets
Utils::String::Replace(name, "mp/", "");
Utils::String::Replace(name, ".d3dbsp", "");
Components::FileSystem::File ents(Utils::String::VA("mapents/%s.ents", name.c_str()));
Components::FileSystem::File ents(Utils::String::VA("mapents/%s.ents", name.data()));
if (ents.exists())
{
Game::MapEnts* entites = builder->getAllocator()->allocate<Game::MapEnts>();
@ -37,20 +37,31 @@ namespace Assets
}
else
{
entites->name = builder->getAllocator()->duplicateString(Utils::String::VA("maps/mp/%s.d3dbsp", name.data()));
entites->stageCount = 1;
entites->stages = builder->getAllocator()->allocate<Game::Stage>();
entites->stages[0].stageName = "stage 0";
entites->stages[0].flags = 0x10400;
}
entites->entityString = builder->getAllocator()->duplicateString(ents.getBuffer());
entites->numEntityChars = ents.getBuffer().size() + 1;
std::string entityString = ents.getBuffer();
entites->name = builder->getAllocator()->duplicateString(Utils::String::VA("maps/mp/%s.d3dbsp", name.data()));
entites->entityString = builder->getAllocator()->duplicateString(entityString);
entites->numEntityChars = entityString.size() + 1;
header->mapEnts = entites;
}
}
void IMapEnts::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{
Utils::Entities memEnts(header.mapEnts->entityString, header.mapEnts->numEntityChars);
for(auto& model : memEnts.getModels())
{
builder->loadAssetByName(Game::XAssetType::ASSET_TYPE_XMODEL, model, false);
}
}
void IMapEnts::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{
AssertSize(Game::MapEnts, 44);

View File

@ -7,6 +7,7 @@ namespace Assets
public:
virtual Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_MAP_ENTS; };
virtual void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
virtual void load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder) override;
};

View File

@ -881,7 +881,7 @@ namespace Assets
clipMap->checksum = reader.read<int>();
clipMap->mapEnts = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_MAP_ENTS, Utils::String::VA("maps/mp/%s.d3dbsp", name.c_str()), builder).mapEnts;
clipMap->mapEnts = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_MAP_ENTS, Utils::String::VA("maps/mp/%s.d3dbsp", name.data()), builder).mapEnts;
// This mustn't be null and has to have at least 1 'valid' entry.
if (!clipMap->smodelNodeCount || !clipMap->smodelNodes)

View File

@ -105,6 +105,7 @@ template <size_t S> class Sizer { };
#include "Utils/String.hpp"
#include "Utils/Hooking.hpp"
#include "Utils/Library.hpp"
#include "Utils/Entities.hpp"
#include "Utils/InfoString.hpp"
#include "Utils/Compression.hpp"
#include "Utils/Cryptography.hpp"

169
src/Utils/Entities.cpp Normal file
View File

@ -0,0 +1,169 @@
#include "STDInclude.hpp"
namespace Utils
{
std::string Entities::build()
{
std::string entityString;
for (auto& entity : this->entities)
{
entityString.append("{\n");
for (auto& property : entity)
{
entityString.push_back('"');
entityString.append(property.first);
entityString.append("\" \"");
entityString.append(property.second);
entityString.append("\"\n");
}
entityString.append("}\n");
}
return entityString;
}
std::vector<std::string> Entities::getModels()
{
std::vector<std::string> models;
for (auto& entity : this->entities)
{
if(entity.find("model") != entity.end())
{
std::string model = entity["model"];
if(!model.empty() && model[0] != '*') // Skip brushmodels
{
if (std::find(models.begin(), models.end(), model) == models.end())
{
models.push_back(model);
}
}
}
}
return models;
}
void Entities::deleteTriggers()
{
for(auto i = this->entities.begin(); i != this->entities.end();)
{
if(i->find("classname") != i->end())
{
std::string classname = (*i)["classname"];
if(Utils::String::StartsWith(classname, "trigger_"))
{
i = this->entities.erase(i);
continue;
}
}
++i;
}
}
void Entities::convertTurrets()
{
for (auto& entity : this->entities)
{
if (entity.find("classname") != entity.end())
{
if (entity["classname"] == "misc_turret"s)
{
entity["weaponinfo"] = "turret_minigun_mp";
entity["model"] = "weapon_minigun";
}
}
}
}
void Entities::deleteWeapons(bool keepTurrets)
{
for (auto i = this->entities.begin(); i != this->entities.end();)
{
if (i->find("weaponinfo") != i->end())
{
if (!keepTurrets || i->find("classname") == i->end() || (*i)["classname"] != "misc_turret"s)
{
i = this->entities.erase(i);
continue;
}
}
++i;
}
}
void Entities::parse(std::string buffer)
{
int parseState = 0;
std::string key;
std::string value;
std::unordered_map<std::string, std::string> entity;
for(unsigned int i = 0; i < buffer.size(); ++i)
{
char character = buffer[i];
if(character == '{')
{
entity.clear();
}
switch(character)
{
case '{':
{
entity.clear();
break;
}
case '}':
{
this->entities.push_back(entity);
entity.clear();
break;
}
case '"':
{
if (parseState == PARSE_AWAIT_KEY)
{
key.clear();
parseState = PARSE_READ_KEY;
}
else if (parseState == PARSE_READ_KEY)
{
parseState = PARSE_AWAIT_VALUE;
}
else if (parseState == PARSE_AWAIT_VALUE)
{
value.clear();
parseState = PARSE_READ_VALUE;
}
else if (parseState == PARSE_READ_VALUE)
{
entity[Utils::String::ToLower(key)] = value;
parseState = PARSE_AWAIT_KEY;
}
else
{
throw std::runtime_error("Parsing error!");
}
break;
}
default:
{
if(parseState == PARSE_READ_KEY) key.push_back(character);
else if (parseState == PARSE_READ_VALUE) value.push_back(character);
break;
}
}
}
}
}

32
src/Utils/Entities.hpp Normal file
View File

@ -0,0 +1,32 @@
#pragma once
namespace Utils
{
class Entities
{
public:
Entities() {};
Entities(const char* string, size_t lenPlusOne) : Entities(std::string(string, lenPlusOne - 1)) {}
Entities(std::string buffer) : Entities() { this->parse(buffer); };
Entities(const Entities &obj) : entities(obj.entities) {};
std::string build();
std::vector<std::string> getModels();
void deleteTriggers();
void deleteWeapons(bool keepTurrets);
void convertTurrets();
private:
enum
{
PARSE_AWAIT_KEY,
PARSE_READ_KEY,
PARSE_AWAIT_VALUE,
PARSE_READ_VALUE,
};
std::vector<std::unordered_map<std::string, std::string>> entities;
void parse(std::string buffer);
};
}