1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-15 01:24:45 +02:00

Slight tweaking of logging of h3m edge cases

This commit is contained in:
Ivan Savenko
2023-04-11 17:46:08 +03:00
parent f84665b5ec
commit 2c2c2c8fe0
2 changed files with 137 additions and 136 deletions

View File

@ -195,7 +195,7 @@ void CMapLoaderH3M::readPlayerInfo()
if(features.levelSOD) if(features.levelSOD)
reader->skipUnused(1); //TODO: check meaning? reader->skipUnused(1); //TODO: check meaning?
std::set<TFaction> allowedFactions; std::set<FactionID> allowedFactions;
reader->readBitmask(allowedFactions, features.factionsBytes, features.factionsCount, false); reader->readBitmask(allowedFactions, features.factionsBytes, features.factionsCount, false);
@ -331,7 +331,7 @@ void CMapLoaderH3M::readVictoryLossConditions()
if(playersOnMap == 1) if(playersOnMap == 1)
{ {
logGlobal->warn("Map %s has only one player but allows normal victory?", mapHeader->name); logGlobal->warn("Map %s: Only one player exists, but normal victory allowed!", mapName);
allowNormalVictory = false; // makes sense? Not much. Works as H3? Yes! allowNormalVictory = false; // makes sense? Not much. Works as H3? Yes!
} }
} }
@ -847,13 +847,13 @@ bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot)
if(!art) if(!art)
{ {
logGlobal->warn("Invalid artifact in hero's backpack, ignoring..."); logGlobal->warn("Map '%s': Invalid artifact in hero's backpack, ignoring...", mapName);
return false; return false;
} }
if(art->isBig() && slot >= GameConstants::BACKPACK_START) if(art->isBig() && slot >= GameConstants::BACKPACK_START)
{ {
logGlobal->warn("A big artifact (war machine) in hero's backpack, ignoring..."); logGlobal->warn("Map '%s': A big artifact (war machine) in hero's backpack, ignoring...", mapName);
return false; return false;
} }
@ -868,7 +868,7 @@ bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot)
} }
else else
{ {
logGlobal->debug("Artifact '%s' can't be put at the slot %d", artifact->artType->getNameTranslated(), slot); logGlobal->warn("Map '%s': Artifact '%s' can't be put at the slot %d", mapName, artifact->artType->getNameTranslated(), slot);
return false; return false;
} }
@ -1070,17 +1070,17 @@ CGObjectInstance * CMapLoaderH3M::readScholar()
object->bonusType = static_cast<CGScholar::EBonusType>(reader->readUInt8()); object->bonusType = static_cast<CGScholar::EBonusType>(reader->readUInt8());
object->bonusID = reader->readUInt8(); object->bonusID = reader->readUInt8();
reader->skipZero(6); reader->skipZero(6);
return object; return object;
} }
CGObjectInstance * CMapLoaderH3M::readGarrison(const int3 & mapPosition) CGObjectInstance * CMapLoaderH3M::readGarrison(const int3 & mapPosition)
{ {
auto * object = new CGGarrison(); auto * object = new CGGarrison();
setOwnerAndValidate(mapPosition, object, reader->readPlayer32()); setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
readCreatureSet(object, 7); readCreatureSet(object, 7);
if(features.levelAB) if(features.levelAB)
object->removableUnits = reader->readBool(); object->removableUnits = reader->readBool();
else else
object->removableUnits = true; object->removableUnits = true;
@ -1129,26 +1129,26 @@ CGObjectInstance * CMapLoaderH3M::readResource(const int3 & mapPosition, std::sh
CGObjectInstance * CMapLoaderH3M::readMine(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate) CGObjectInstance * CMapLoaderH3M::readMine(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{ {
auto * object = new CGMine(); auto * object = new CGMine();
if(objectTemplate->subid < 7) if(objectTemplate->subid < 7)
{ {
setOwnerAndValidate(mapPosition, object, reader->readPlayer32()); setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
} }
else else
{ {
object->setOwner(PlayerColor::NEUTRAL); object->setOwner(PlayerColor::NEUTRAL);
reader->readBitmask(object->abandonedMineResources, features.resourcesBytes, features.resourcesCount, false); reader->readBitmask(object->abandonedMineResources, features.resourcesBytes, features.resourcesCount, false);
} }
return object; return object;
} }
CGObjectInstance * CMapLoaderH3M::readDwelling(const int3 & position) CGObjectInstance * CMapLoaderH3M::readDwelling(const int3 & position)
{ {
auto * object = new CGDwelling(); auto * object = new CGDwelling();
setOwnerAndValidate(position, object, reader->readPlayer32()); setOwnerAndValidate(position, object, reader->readPlayer32());
return object; return object;
} }
CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate) CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{ {
auto * object = new CGDwelling(); auto * object = new CGDwelling();
@ -1167,13 +1167,13 @@ CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, s
break; break;
default: default:
throw std::runtime_error("Invalid random dwelling format"); throw std::runtime_error("Invalid random dwelling format");
} }
spec->owner = object; spec->owner = object;
setOwnerAndValidate(mapPosition, object, reader->readPlayer32()); setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
//216 and 217 //216 and 217
if(auto * castleSpec = dynamic_cast<CCreGenAsCastleInfo *>(spec)) if(auto * castleSpec = dynamic_cast<CCreGenAsCastleInfo *>(spec))
{ {
castleSpec->instanceId = ""; castleSpec->instanceId = "";
castleSpec->identifier = reader->readUInt32(); castleSpec->identifier = reader->readUInt32();
@ -1218,13 +1218,13 @@ CGObjectInstance * CMapLoaderH3M::readShrine()
} }
CGObjectInstance * CMapLoaderH3M::readHeroPlaceholder(const int3 & mapPosition) CGObjectInstance * CMapLoaderH3M::readHeroPlaceholder(const int3 & mapPosition)
{ {
auto * object = new CGHeroPlaceholder(); auto * object = new CGHeroPlaceholder();
setOwnerAndValidate(mapPosition, object, reader->readPlayer()); setOwnerAndValidate(mapPosition, object, reader->readPlayer());
HeroTypeID htid = reader->readHero(); //hero type id HeroTypeID htid = reader->readHero(); //hero type id
object->subID = htid.getNum(); object->subID = htid.getNum();
if(htid.getNum() == -1) if(htid.getNum() == -1)
{ {
@ -1252,7 +1252,7 @@ CGObjectInstance * CMapLoaderH3M::readGeneric(const int3 & mapPosition, std::sha
if(VLC->objtypeh->knownSubObjects(objectTemplate->id).count(objectTemplate->subid)) if(VLC->objtypeh->knownSubObjects(objectTemplate->id).count(objectTemplate->subid))
return VLC->objtypeh->getHandlerFor(objectTemplate->id, objectTemplate->subid)->create(objectTemplate); return VLC->objtypeh->getHandlerFor(objectTemplate->id, objectTemplate->subid)->create(objectTemplate);
logGlobal->warn("Unrecognized object: %d:%d ('%s') at %s on map '%s'", objectTemplate->id.toEnum(), objectTemplate->subid, objectTemplate->animationFile, mapPosition.toString(), map->name); logGlobal->warn("Map '%s': Unrecognized object %d:%d ('%s') at %s found!", mapName, objectTemplate->id.toEnum(), objectTemplate->subid, objectTemplate->animationFile, mapPosition.toString());
return new CGObjectInstance(); return new CGObjectInstance();
} }
@ -1268,16 +1268,16 @@ CGObjectInstance * CMapLoaderH3M::readQuestGuard(const int3 & mapPosition)
{ {
auto * guard = new CGQuestGuard(); auto * guard = new CGQuestGuard();
readQuest(guard, mapPosition); readQuest(guard, mapPosition);
return guard; return guard;
} }
CGObjectInstance * CMapLoaderH3M::readShipyard(const int3 & mapPosition) CGObjectInstance * CMapLoaderH3M::readShipyard(const int3 & mapPosition)
{ {
auto * object = new CGShipyard(); auto * object = new CGShipyard();
setOwnerAndValidate(mapPosition, object, reader->readPlayer32()); setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
return object; return object;
} }
CGObjectInstance * CMapLoaderH3M::readBorderGuard() CGObjectInstance * CMapLoaderH3M::readBorderGuard()
{ {
return new CGBorderGuard(); return new CGBorderGuard();
@ -1293,16 +1293,16 @@ CGObjectInstance * CMapLoaderH3M::readBorderGate(const int3 & mapPosition, std::
return new CGObjectInstance(); return new CGObjectInstance();
logGlobal->warn("Map '%s: Quest gates at %s are not implemented!", mapName, mapPosition.toString()); logGlobal->warn("Map '%s: Quest gates at %s are not implemented!", mapName, mapPosition.toString());
return readQuestGuard(mapPosition); return readQuestGuard(mapPosition);
} }
CGObjectInstance * CMapLoaderH3M::readLighthouse(const int3 & mapPosition) CGObjectInstance * CMapLoaderH3M::readLighthouse(const int3 & mapPosition)
{ {
auto * object = new CGLighthouse(); auto * object = new CGLighthouse();
setOwnerAndValidate(mapPosition, object, reader->readPlayer32()); setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
return object; return object;
} }
CGObjectInstance * CMapLoaderH3M::readBank(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate) CGObjectInstance * CMapLoaderH3M::readBank(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{ {
if(features.levelHOTA3) if(features.levelHOTA3)
@ -1376,13 +1376,13 @@ CGObjectInstance * CMapLoaderH3M::readObject(std::shared_ptr<const ObjectTemplat
return readWitchHut(); return readWitchHut();
case Obj::SCHOLAR: case Obj::SCHOLAR:
return readScholar(); return readScholar();
case Obj::GARRISON: case Obj::GARRISON:
case Obj::GARRISON2: case Obj::GARRISON2:
return readGarrison(mapPosition); return readGarrison(mapPosition);
case Obj::ARTIFACT: case Obj::ARTIFACT:
case Obj::RANDOM_ART: case Obj::RANDOM_ART:
case Obj::RANDOM_TREASURE_ART: case Obj::RANDOM_TREASURE_ART:
case Obj::RANDOM_MINOR_ART: case Obj::RANDOM_MINOR_ART:
case Obj::RANDOM_MAJOR_ART: case Obj::RANDOM_MAJOR_ART:
@ -1424,13 +1424,13 @@ CGObjectInstance * CMapLoaderH3M::readObject(std::shared_ptr<const ObjectTemplat
return readDwellingRandom(mapPosition, objectTemplate); return readDwellingRandom(mapPosition, objectTemplate);
case Obj::QUEST_GUARD: case Obj::QUEST_GUARD:
return readQuestGuard(mapPosition); return readQuestGuard(mapPosition);
case Obj::SHIPYARD: case Obj::SHIPYARD:
return readShipyard(mapPosition); return readShipyard(mapPosition);
case Obj::HERO_PLACEHOLDER: case Obj::HERO_PLACEHOLDER:
return readHeroPlaceholder(mapPosition); return readHeroPlaceholder(mapPosition);
case Obj::BORDERGUARD: case Obj::BORDERGUARD:
return readBorderGuard(); return readBorderGuard();
@ -1439,13 +1439,13 @@ CGObjectInstance * CMapLoaderH3M::readObject(std::shared_ptr<const ObjectTemplat
return readBorderGate(mapPosition, objectTemplate); return readBorderGate(mapPosition, objectTemplate);
case Obj::PYRAMID: case Obj::PYRAMID:
return readPyramid(mapPosition, objectTemplate); return readPyramid(mapPosition, objectTemplate);
case Obj::LIGHTHOUSE: case Obj::LIGHTHOUSE:
return readLighthouse(mapPosition); return readLighthouse(mapPosition);
case Obj::CREATURE_BANK: case Obj::CREATURE_BANK:
case Obj::DERELICT_SHIP: case Obj::DERELICT_SHIP:
case Obj::DRAGON_UTOPIA: case Obj::DRAGON_UTOPIA:
case Obj::CRYPT: case Obj::CRYPT:
case Obj::SHIPWRECK: case Obj::SHIPWRECK:
@ -1538,40 +1538,40 @@ void CMapLoaderH3M::readCreatureSet(CCreatureSet * out, int number)
out->putStack(SlotID(index), result); out->putStack(SlotID(index), result);
} }
out->validTypes(true); out->validTypes(true);
} }
void CMapLoaderH3M::setOwnerAndValidate(const int3 & mapPosition, CGObjectInstance * object, const PlayerColor & owner) void CMapLoaderH3M::setOwnerAndValidate(const int3 & mapPosition, CGObjectInstance * object, const PlayerColor & owner)
{ {
assert(owner.isValidPlayer() || owner == PlayerColor::NEUTRAL); assert(owner.isValidPlayer() || owner == PlayerColor::NEUTRAL);
if(owner == PlayerColor::NEUTRAL) if(owner == PlayerColor::NEUTRAL)
{ {
object->setOwner(PlayerColor::NEUTRAL); object->setOwner(PlayerColor::NEUTRAL);
return; return;
} }
if(!owner.isValidPlayer()) if(!owner.isValidPlayer())
{ {
object->setOwner(PlayerColor::NEUTRAL); object->setOwner(PlayerColor::NEUTRAL);
logGlobal->warn("Map '%s': Object at %s - owned by invalid player %d! Will be set to neutral!", mapName, mapPosition.toString(), int(owner.getNum())); logGlobal->warn("Map '%s': Object at %s - owned by invalid player %d! Will be set to neutral!", mapName, mapPosition.toString(), int(owner.getNum()));
return; return;
} }
if(!mapHeader->players[owner.getNum()].canAnyonePlay()) if(!mapHeader->players[owner.getNum()].canAnyonePlay())
{ {
object->setOwner(PlayerColor::NEUTRAL); object->setOwner(PlayerColor::NEUTRAL);
logGlobal->warn("Map '%s': Object at %s - owned by non-existing player %d! Will be set to neutral!", mapName, mapPosition.toString(), int(owner.getNum()) logGlobal->warn("Map '%s': Object at %s - owned by non-existing player %d! Will be set to neutral!", mapName, mapPosition.toString(), int(owner.getNum())
); );
return; return;
} }
object->setOwner(owner); object->setOwner(owner);
} }
CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID) CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
{ {
auto * object = new CGHeroInstance(); auto * object = new CGHeroInstance();
if(features.levelAB) if(features.levelAB)
{ {
@ -1592,13 +1592,13 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
delete object; delete object;
object = elem; object = elem;
break; break;
} }
} }
setOwnerAndValidate(mapPosition, object, owner); setOwnerAndValidate(mapPosition, object, owner);
object->portrait = object->subID; object->portrait = object->subID;
for(auto & elem : map->disposedHeroes) for(auto & elem : map->disposedHeroes)
{ {
if(elem.heroId == object->subID) if(elem.heroId == object->subID)
{ {
@ -1973,14 +1973,14 @@ void CMapLoaderH3M::readQuest(IQuestObject * guard, const int3 & position)
CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate) CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
{ {
auto * object = new CGTownInstance(); auto * object = new CGTownInstance();
if(features.levelAB) if(features.levelAB)
object->identifier = reader->readUInt32(); object->identifier = reader->readUInt32();
setOwnerAndValidate(position, object, reader->readPlayer()); setOwnerAndValidate(position, object, reader->readPlayer());
bool hasName = reader->readBool(); bool hasName = reader->readBool();
if(hasName) if(hasName)
object->setNameTranslated(readLocalizedString(TextIdentifier("town", position.x, position.y, position.z, "name"))); object->setNameTranslated(readLocalizedString(TextIdentifier("town", position.x, position.y, position.z, "name")));
bool hasGarrison = reader->readBool(); bool hasGarrison = reader->readBool();
if(hasGarrison) if(hasGarrison)

View File

@ -118,7 +118,8 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
{ {
ui32 length; ui32 length;
load(length); load(length);
if(length > 500000) //NOTE: also used for h3m's embedded in campaigns, so it may be quite large in some cases (e.g. XXL maps with multiple objects)
if(length > 1000000)
{ {
logGlobal->warn("Warning: very big length: %d", length); logGlobal->warn("Warning: very big length: %d", length);
reader->reportState(logGlobal); reader->reportState(logGlobal);