1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Make string instance names persistent

This commit is contained in:
AlexVinS
2016-02-22 19:26:42 +03:00
parent ac281f3fec
commit dc5ad7d7b3
10 changed files with 83 additions and 87 deletions

View File

@@ -386,6 +386,7 @@ DLL_LINKAGE void RemoveObject::applyGs( CGameState *gs )
//If hero on Boat is removed, the Boat disappears //If hero on Boat is removed, the Boat disappears
if(h->boat) if(h->boat)
{ {
gs->map->instanceNames.erase(h->boat->instanceName);
gs->map->objects[h->boat->id.getNum()].dellNull(); gs->map->objects[h->boat->id.getNum()].dellNull();
h->boat = nullptr; h->boat = nullptr;
} }
@@ -430,7 +431,7 @@ DLL_LINKAGE void RemoveObject::applyGs( CGameState *gs )
}; };
event.trigger = event.trigger.morph(patcher); event.trigger = event.trigger.morph(patcher);
} }
gs->map->instanceNames.erase(obj->instanceName);
gs->map->objects[id.getNum()].dellNull(); gs->map->objects[id.getNum()].dellNull();
gs->map->calculateGuardingGreaturePositions(); gs->map->calculateGuardingGreaturePositions();
} }

View File

@@ -139,18 +139,6 @@ CGObjectInstance::~CGObjectInstance()
{ {
} }
const std::string & CGObjectInstance::getStringId() const
{
if(stringId == "")
{
boost::format fmt("%s_%d");
fmt % typeName % id.getNum();
stringId = fmt.str();
}
return stringId;
}
void CGObjectInstance::setOwner(PlayerColor ow) void CGObjectInstance::setOwner(PlayerColor ow)
{ {
tempOwner = ow; tempOwner = ow;

View File

@@ -118,14 +118,13 @@ public:
/// If true hero can visit this object only from neighbouring tiles and can't stand on this object /// If true hero can visit this object only from neighbouring tiles and can't stand on this object
bool blockVisit; bool blockVisit;
std::string instanceName;
std::string typeName; std::string typeName;
std::string subTypeName; std::string subTypeName;
CGObjectInstance(); CGObjectInstance();
~CGObjectInstance(); ~CGObjectInstance();
const std::string & getStringId() const;
/// "center" tile from which the sight distance is calculated /// "center" tile from which the sight distance is calculated
int3 getSightCenter() const; int3 getSightCenter() const;
@@ -177,13 +176,13 @@ public:
///Entry point of binary (de-)serialization ///Entry point of binary (de-)serialization
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & pos & ID & subID & id & tempOwner & blockVisit & appearance;
//definfo is handled by map serializer
if(version >= 759) if(version >= 759)
{ {
h & typeName & subTypeName; h & instanceName & typeName & subTypeName;
} }
h & pos & ID & subID & id & tempOwner & blockVisit & appearance;
//definfo is handled by map serializer
} }
///Entry point of Json (de-)serialization ///Entry point of Json (de-)serialization
@@ -200,9 +199,6 @@ protected:
virtual void serializeJsonOptions(JsonSerializeFormat & handler); virtual void serializeJsonOptions(JsonSerializeFormat & handler);
void serializeJsonOwner(JsonSerializeFormat & handler); void serializeJsonOwner(JsonSerializeFormat & handler);
private:
mutable std::string stringId;///<alternate id, dynamically generated, do not serialize
}; };
/// function object which can be used to find an object with an specific sub ID /// function object which can be used to find an object with an specific sub ID

View File

@@ -558,6 +558,32 @@ void CMap::addQuest(CGObjectInstance * quest)
quests.push_back(q->quest); quests.push_back(q->quest);
} }
void CMap::addNewObject(CGObjectInstance * obj)
{
if(obj->id != ObjectInstanceID(objects.size()))
throw std::runtime_error("Invalid object instance id");
if(obj->instanceName == "")
throw std::runtime_error("Object instance name missing");
auto it = instanceNames.find(obj->instanceName);
if(it != instanceNames.end())
throw std::runtime_error("Object instance name duplicated:"+obj->instanceName);
objects.push_back(obj);
instanceNames[obj->instanceName] = obj;
addBlockVisTiles(obj);
if(obj->ID == Obj::TOWN)
{
towns.push_back(static_cast<CGTownInstance *>(obj));
}
if(obj->ID == Obj::HERO)
{
heroesOnMap.push_back(static_cast<CGHeroInstance*>(obj));
}
}
void CMap::initTerrain() void CMap::initTerrain()
{ {
int level = twoLevel ? 2 : 1; int level = twoLevel ? 2 : 1;

View File

@@ -299,6 +299,7 @@ public:
void addNewArtifactInstance(CArtifactInstance * art); void addNewArtifactInstance(CArtifactInstance * art);
void eraseArtifactInstance(CArtifactInstance * art); void eraseArtifactInstance(CArtifactInstance * art);
void addQuest(CGObjectInstance * quest); void addQuest(CGObjectInstance * quest);
void addNewObject(CGObjectInstance * obj);
/// Gets object of specified type on requested position /// Gets object of specified type on requested position
const CGObjectInstance * getObjectiveObjectFrom(int3 pos, Obj::EObj type); const CGObjectInstance * getObjectiveObjectFrom(int3 pos, Obj::EObj type);
@@ -336,6 +337,8 @@ public:
int3 ***guardingCreaturePositions; int3 ***guardingCreaturePositions;
std::map<std::string, ConstTransitivePtr<CGObjectInstance> > instanceNames;
private: private:
/// a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground /// a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground
TerrainTile*** terrain; TerrainTile*** terrain;
@@ -403,5 +406,10 @@ public:
h & CGObelisk::obeliskCount & CGObelisk::visited; h & CGObelisk::obeliskCount & CGObelisk::visited;
h & CGTownInstance::merchantArtifacts; h & CGTownInstance::merchantArtifacts;
h & CGTownInstance::universitySkills; h & CGTownInstance::universitySkills;
if(version >= 759)
{
h & instanceNames;
}
} }
}; };

View File

@@ -1043,16 +1043,12 @@ void CInsertObjectOperation::execute()
{ {
obj->pos = pos; obj->pos = pos;
obj->id = ObjectInstanceID(map->objects.size()); obj->id = ObjectInstanceID(map->objects.size());
map->objects.push_back(obj);
if(obj->ID == Obj::TOWN) boost::format fmt("%s_%d");
{ fmt % obj->typeName % obj->id.getNum();
map->towns.push_back(static_cast<CGTownInstance *>(obj)); obj->instanceName = fmt.str();
}
if(obj->ID == Obj::HERO) map->addNewObject(obj);
{
map->heroesOnMap.push_back(static_cast<CGHeroInstance*>(obj));
}
map->addBlockVisTiles(obj);
} }
void CInsertObjectOperation::undo() void CInsertObjectOperation::undo()

View File

@@ -1459,16 +1459,16 @@ void CMapLoaderH3M::readObjects()
} }
nobj->appearance = objTempl; nobj->appearance = objTempl;
assert(idToBeGiven == ObjectInstanceID(map->objects.size())); assert(idToBeGiven == ObjectInstanceID(map->objects.size()));
map->objects.push_back(nobj);
if(nobj->ID == Obj::TOWN)
{ {
map->towns.push_back(static_cast<CGTownInstance *>(nobj)); //TODO: define valid typeName and subtypeName fro H3M maps
} //boost::format fmt("%s_%d");
if(nobj->ID == Obj::HERO) //fmt % nobj->typeName % nobj->id.getNum();
{ boost::format fmt("obj_%d");
logGlobal->debugStream() << "Hero: " << VLC->heroh->heroes[nobj->subID]->name << " at " << objPos; fmt % nobj->id.getNum();
map->heroesOnMap.push_back(static_cast<CGHeroInstance*>(nobj)); nobj->instanceName = fmt.str();
} }
map->addNewObject(nobj);
} }
std::sort(map->heroesOnMap.begin(), map->heroesOnMap.end(), [](const ConstTransitivePtr<CGHeroInstance> & a, const ConstTransitivePtr<CGHeroInstance> & b) std::sort(map->heroesOnMap.begin(), map->heroesOnMap.end(), [](const ConstTransitivePtr<CGHeroInstance> & a, const ConstTransitivePtr<CGHeroInstance> & b)

View File

@@ -150,21 +150,6 @@ namespace TerrainDetail
}; };
} }
static std::string tailString(const std::string & input, char separator)
{
std::string ret;
size_t splitPos = input.find(separator);
if (splitPos != std::string::npos)
ret = input.substr(splitPos + 1);
return ret;
}
static si32 extractNumber(const std::string & input, char separator)
{
std::string tmp = tailString(input, separator);
return atoi(tmp.c_str());
}
///CMapFormatJson ///CMapFormatJson
const int CMapFormatJson::VERSION_MAJOR = 1; const int CMapFormatJson::VERSION_MAJOR = 1;
const int CMapFormatJson::VERSION_MINOR = 0; const int CMapFormatJson::VERSION_MINOR = 0;
@@ -547,11 +532,6 @@ void CMapLoaderJson::readMap()
readTerrain(); readTerrain();
readObjects(); readObjects();
// Calculate blocked / visitable positions
for(auto & elem : map->objects)
{
map->addBlockVisTiles(elem);
}
map->calculateGuardingGreaturePositions(); map->calculateGuardingGreaturePositions();
} }
@@ -747,7 +727,7 @@ void CMapLoaderJson::readTerrain()
} }
CMapLoaderJson::MapObjectLoader::MapObjectLoader(CMapLoaderJson * _owner, JsonMap::value_type& json): CMapLoaderJson::MapObjectLoader::MapObjectLoader(CMapLoaderJson * _owner, JsonMap::value_type& json):
owner(_owner), instance(nullptr),id(-1), jsonKey(json.first), configuration(json.second), internalId(extractNumber(jsonKey, '_')) owner(_owner), instance(nullptr),id(-1), jsonKey(json.first), configuration(json.second)
{ {
} }
@@ -788,7 +768,8 @@ void CMapLoaderJson::MapObjectLoader::construct()
instance = handler->create(ObjectTemplate()); instance = handler->create(ObjectTemplate());
instance->id = ObjectInstanceID(owner->map->objects.size()); instance->id = ObjectInstanceID(owner->map->objects.size());
owner->map->objects.push_back(instance); instance->instanceName = jsonKey;
owner->map->addNewObject(instance);
} }
void CMapLoaderJson::MapObjectLoader::configure() void CMapLoaderJson::MapObjectLoader::configure()
@@ -800,16 +781,7 @@ void CMapLoaderJson::MapObjectLoader::configure()
instance->serializeJson(handler); instance->serializeJson(handler);
if(instance->ID == Obj::TOWN) if(auto art = dynamic_cast<CGArtifact *>(instance))
{
owner->map->towns.push_back(static_cast<CGTownInstance *>(instance));
}
else if(instance->ID == Obj::HERO)
{
logGlobal->debugStream() << "Hero: " << VLC->heroh->heroes[instance->subID]->name << " at " << instance->pos;
owner->map->heroesOnMap.push_back(static_cast<CGHeroInstance *>(instance));
}
else if(auto art = dynamic_cast<CGArtifact *>(instance))
{ {
//todo: find better place for this code //todo: find better place for this code
@@ -848,13 +820,6 @@ void CMapLoaderJson::readObjects()
for(auto & p : data.Struct()) for(auto & p : data.Struct())
loaders.push_back(vstd::make_unique<MapObjectLoader>(this, p)); loaders.push_back(vstd::make_unique<MapObjectLoader>(this, p));
auto sortInfos = [](const std::unique_ptr<MapObjectLoader> & lhs, const std::unique_ptr<MapObjectLoader> & rhs) -> bool
{
return lhs->internalId < rhs->internalId;
};
boost::sort(loaders, sortInfos);//this makes instance ids consistent after save-load, needed for testing
//todo: use internalId in CMap
for(auto & ptr : loaders) for(auto & ptr : loaders)
ptr->construct(); ptr->construct();
@@ -1003,7 +968,7 @@ void CMapSaverJson::writeObjects()
for(CGObjectInstance * obj : map->objects) for(CGObjectInstance * obj : map->objects)
{ {
auto temp = handler.enterStruct(obj->getStringId()); auto temp = handler.enterStruct(obj->instanceName);
obj->serializeJson(handler); obj->serializeJson(handler);
} }

View File

@@ -165,7 +165,7 @@ private:
ObjectInstanceID id; ObjectInstanceID id;
std::string jsonKey;//full id defined by map creator std::string jsonKey;//full id defined by map creator
JsonNode & configuration; JsonNode & configuration;
si32 internalId;//unique part of id defined by map creator (also = quest identifier)
///constructs object (without configuration) ///constructs object (without configuration)
void construct(); void construct();

View File

@@ -182,7 +182,7 @@ void MapComparer::compareOptions()
void MapComparer::compareObject(const CGObjectInstance * actual, const CGObjectInstance * expected) void MapComparer::compareObject(const CGObjectInstance * actual, const CGObjectInstance * expected)
{ {
BOOST_CHECK_EQUAL(actual->getStringId(), expected->getStringId()); BOOST_CHECK_EQUAL(actual->instanceName, expected->instanceName);
BOOST_CHECK_EQUAL(typeid(actual).name(), typeid(expected).name());//todo: remove and use just comparison BOOST_CHECK_EQUAL(typeid(actual).name(), typeid(expected).name());//todo: remove and use just comparison
std::string actualFullID = boost::to_string(boost::format("%s(%d)|%s(%d) %d") % actual->typeName % actual->ID % actual->subTypeName % actual->subID % actual->tempOwner); std::string actualFullID = boost::to_string(boost::format("%s(%d)|%s(%d) %d") % actual->typeName % actual->ID % actual->subTypeName % actual->subID % actual->tempOwner);
@@ -190,18 +190,34 @@ void MapComparer::compareObject(const CGObjectInstance * actual, const CGObjectI
BOOST_CHECK_EQUAL(actualFullID, expectedFullID); BOOST_CHECK_EQUAL(actualFullID, expectedFullID);
BOOST_CHECK_EQUAL(actual->pos, expected->pos); BOOST_CHECK_EQUAL(actual->pos, expected->pos);
//BOOST_CHECK_EQUAL(actual->tempOwner,expected->tempOwner);
} }
void MapComparer::compareObjects() void MapComparer::compareObjects()
{ {
BOOST_CHECK_EQUAL(actual->objects.size(), expected->objects.size()); BOOST_CHECK_EQUAL(actual->objects.size(), expected->objects.size());
for(size_t idx = 0; idx < std::min(actual->objects.size(), expected->objects.size()); idx++) for(size_t idx = 0; idx < expected->objects.size(); idx++)
{ {
BOOST_REQUIRE_EQUAL(idx, expected->objects[idx]->id.getNum()); auto expectedObject = expected->objects[idx];
BOOST_CHECK_EQUAL(idx, actual->objects[idx]->id.getNum());
compareObject(actual->objects[idx], expected->objects[idx]); BOOST_REQUIRE_EQUAL(idx, expectedObject->id.getNum());
{
auto it = expected->instanceNames.find(expectedObject->instanceName);
BOOST_REQUIRE(it != expected->instanceNames.end());
}
{
auto it = actual->instanceNames.find(expectedObject->instanceName);
BOOST_REQUIRE(it != expected->instanceNames.end());
auto actualObject = it->second;
compareObject(actualObject, expectedObject);
}
} }
} }