1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

- moved json-related functions (e.g. ParseBonus) into JsonUtils namespace

- replaced JsonNode::toStdVector with more universal convertTo
- some renaming in StartInfo
This commit is contained in:
Ivan Savenko 2012-12-02 12:21:44 +00:00
parent ca9033d0e4
commit c9dd80ea6d
20 changed files with 340 additions and 273 deletions

View File

@ -294,7 +294,7 @@ void CTownList::CTownItem::update()
{
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN];
picture->setFrame(iconIndex + 2);
picture->setFrame(iconIndex);
redraw();
}

View File

@ -1202,6 +1202,8 @@ void CAnimImage::setFrame(size_t Frame, size_t Group)
pos.h = img->height();
}
}
else
tlog1 << "Error: accessing unavailable frame " << Group << ":" << Frame << " in CAnimation!\n";
}
void CAnimImage::playerColored(int currPlayer)

View File

@ -860,7 +860,7 @@ void startGame(StartInfo * options, CConnection *serv/* = NULL*/)
{
for(auto it = options->playerInfos.begin(); it != options->playerInfos.end(); ++it)
{
it->second.human = false;
it->second.playerID = PlayerSettings::PLAYER_AI;
}
}
/* const JsonNode& res = settings["video"]["screenRes"];

View File

@ -120,12 +120,12 @@ static void setPlayersFromGame()
static void swapPlayers(PlayerSettings &a, PlayerSettings &b)
{
std::swap(a.human, b.human);
std::swap(a.playerID, b.playerID);
std::swap(a.name, b.name);
if(a.human == 1)
if(a.playerID == 1)
playerColor = a.color;
else if(b.human == 1)
else if(b.playerID == 1)
playerColor = b.color;
}
@ -136,7 +136,7 @@ void setPlayer(PlayerSettings &pset, TPlayerColor player, const std::map<TPlayer
else
pset.name = CGI->generaltexth->allTexts[468];//Computer
pset.human = player;
pset.playerID = player;
if(player == playerNames.begin()->first)
playerColor = pset.color;
}
@ -844,7 +844,7 @@ void CSelectionScreen::startGame()
//there must be at least one human player before game can be started
std::map<TPlayerColor, PlayerSettings>::const_iterator i;
for(i = SEL->sInfo.playerInfos.cbegin(); i != SEL->sInfo.playerInfos.cend(); i++)
if(i->second.human)
if(i->second.playerID != PlayerSettings::PLAYER_AI)
break;
if(i == SEL->sInfo.playerInfos.cend())
@ -951,7 +951,7 @@ void CSelectionScreen::setSInfo(const StartInfo &si)
std::map<TPlayerColor, PlayerSettings>::const_iterator i;
for(i = si.playerInfos.cbegin(); i != si.playerInfos.cend(); i++)
{
if(i->second.human == myNameID)
if(i->second.playerID == myNameID)
{
playerColor = i->first;
break;
@ -1988,10 +1988,10 @@ void InfoCard::showAll(SDL_Surface * to)
int playerSoFar = 0;
for (auto i = SEL->sInfo.playerInfos.cbegin(); i != SEL->sInfo.playerInfos.cend(); i++)
{
if(i->second.human)
if(i->second.playerID != PlayerSettings::PLAYER_AI)
{
printAtLoc(i->second.name, 24, 285 + playerSoFar++ * graphics->fonts[FONT_SMALL]->height, FONT_SMALL, Colors::WHITE, to);
playerNames.erase(i->second.human);
playerNames.erase(i->second.playerID);
}
}
@ -2244,7 +2244,7 @@ void OptionsTab::nextCastle( int player, int dir )
}
PlayerSettings &s = SEL->sInfo.playerInfos[player];
si32 &cur = s.castle;
si16 &cur = s.castle;
auto & allowed = SEL->current->mapHeader->players[s.color].allowedFactions;
if (cur == -2) //no castle - no change
@ -2274,8 +2274,8 @@ void OptionsTab::nextCastle( int player, int dir )
if(s.hero >= 0)
s.hero = -1;
if(cur < 0 && s.bonus == PlayerSettings::bresource)
s.bonus = PlayerSettings::brandom;
if(cur < 0 && s.bonus == PlayerSettings::RESOURCE)
s.bonus = PlayerSettings::RANDOM;
entries[player]->selectButtons();
@ -2293,7 +2293,7 @@ void OptionsTab::nextHero( int player, int dir )
PlayerSettings &s = SEL->sInfo.playerInfos[player];
int old = s.hero;
if (s.castle < 0 || !s.human || s.hero == -2)
if (s.castle < 0 || s.playerID == PlayerSettings::PLAYER_AI || s.hero == PlayerSettings::NONE)
return;
if (s.hero == -1) //random => first/last available
@ -2359,23 +2359,23 @@ void OptionsTab::nextBonus( int player, int dir )
PlayerSettings &s = SEL->sInfo.playerInfos[player];
si8 &ret = s.bonus += dir;
if (s.hero==-2 && !SEL->current->mapHeader->players[s.color].heroesNames.size() && ret==PlayerSettings::bartifact) //no hero - can't be artifact
if (s.hero==-2 && !SEL->current->mapHeader->players[s.color].heroesNames.size() && ret==PlayerSettings::ARTIFACT) //no hero - can't be artifact
{
if (dir<0)
ret=PlayerSettings::brandom;
else ret=PlayerSettings::bgold;
ret=PlayerSettings::RANDOM;
else ret=PlayerSettings::GOLD;
}
if(ret > PlayerSettings::bresource)
ret = PlayerSettings::brandom;
if(ret < PlayerSettings::brandom)
ret = PlayerSettings::bresource;
if(ret > PlayerSettings::RESOURCE)
ret = PlayerSettings::RANDOM;
if(ret < PlayerSettings::RANDOM)
ret = PlayerSettings::RESOURCE;
if (s.castle==-1 && ret==PlayerSettings::bresource) //random castle - can't be resource
if (s.castle==-1 && ret==PlayerSettings::RESOURCE) //random castle - can't be resource
{
if (dir<0)
ret=PlayerSettings::bgold;
else ret=PlayerSettings::brandom;
ret=PlayerSettings::GOLD;
else ret=PlayerSettings::RANDOM;
}
SEL->propagateOptions();
@ -2427,7 +2427,7 @@ void OptionsTab::flagPressed( int color )
else
{
//identify clicked player
int clickedNameID = clicked.human; //human is a number of player, zero means AI
int clickedNameID = clicked.playerID; //human is a number of player, zero means AI
if(clickedNameID > 0 && playerToRestore.id == clickedNameID) //player to restore is about to being replaced -> put him back to the old place
{
@ -2463,10 +2463,10 @@ void OptionsTab::flagPressed( int color )
{
for(auto i = SEL->sInfo.playerInfos.begin(); i != SEL->sInfo.playerInfos.end(); i++)
{
int curNameID = i->second.human;
int curNameID = i->second.playerID;
if(i->first != color && curNameID == newPlayer)
{
assert(i->second.human);
assert(i->second.playerID);
playerToRestore.color = i->first;
playerToRestore.id = newPlayer;
SEL->setPlayer(i->second, 0); //set computer
@ -2584,7 +2584,7 @@ void OptionsTab::PlayerOptionsEntry::selectButtons()
btns[1]->enable();
}
if( (pi.defaultHero() != -1 || !s.human || s.castle < 0) //fixed hero
if( (pi.defaultHero() != -1 || !s.playerID || s.castle < 0) //fixed hero
|| (SEL->isGuest() && s.color != playerColor))//or not our player
{
btns[2]->disable();
@ -2792,20 +2792,20 @@ void OptionsTab::SelectedBox::clickRight( tribool down, bool previousState )
{
switch(val)
{
case PlayerSettings::brandom:
case PlayerSettings::RANDOM:
title = &CGI->generaltexth->allTexts[86]; //{Random Bonus}
description = &CGI->generaltexth->allTexts[94]; //Gold, wood and ore, or an artifact is randomly chosen as your starting bonus
break;
case PlayerSettings::bartifact:
case PlayerSettings::ARTIFACT:
title = &CGI->generaltexth->allTexts[83]; //{Artifact Bonus}
description = &CGI->generaltexth->allTexts[90]; //An artifact is randomly chosen and equipped to your starting hero
break;
case PlayerSettings::bgold:
case PlayerSettings::GOLD:
title = &CGI->generaltexth->allTexts[84]; //{Gold Bonus}
subTitle = &CGI->generaltexth->allTexts[87]; //500-1000
description = &CGI->generaltexth->allTexts[92]; //At the start of the game, 500-1000 gold is added to your Kingdom's resource pool
break;
case PlayerSettings::bresource:
case PlayerSettings::RESOURCE:
{
title = &CGI->generaltexth->allTexts[85]; //{Resource Bonus}
switch(CGI->townh->towns[s.castle].primaryRes)
@ -2909,7 +2909,7 @@ CScenarioInfo::CScenarioInfo(const CMapHeader *mapHeader, const StartInfo *start
for(auto it = startInfo->playerInfos.cbegin(); it != startInfo->playerInfos.cend(); ++it)
{
if(it->second.human)
if(it->second.playerID)
{
playerColor = it->first;
}
@ -3406,7 +3406,7 @@ void CBonusSelection::updateBonusSelection()
int faction = -1;
for(auto it = sInfo.playerInfos.begin(); it != sInfo.playerInfos.end(); ++it)
{
if (it->second.human)
if (it->second.playerID)
{
faction = it->second.castle;
break;
@ -3775,7 +3775,7 @@ void PlayerJoined::apply(CSelectionScreen *selScreen)
//put new player in first slot with AI
for(auto i = SEL->sInfo.playerInfos.begin(); i != SEL->sInfo.playerInfos.end(); i++)
{
if(!i->second.human)
if(!i->second.playerID)
{
selScreen->setPlayer(i->second, connectionID);
selScreen->opt->entries[i->second.color]->selectButtons();

View File

@ -449,10 +449,10 @@ public:
void processPacks();
void setSInfo(const StartInfo &si);
void update() OVERRIDE;
void propagateOptions() OVERRIDE;
void postRequest(ui8 what, ui8 dir) OVERRIDE;
void postChatMessage(const std::string &txt) OVERRIDE;
void update() override;
void propagateOptions() override;
void postRequest(ui8 what, ui8 dir) override;
void postChatMessage(const std::string &txt) override;
void propagateNames();
void showAll(SDL_Surface *to);
};

View File

@ -304,9 +304,9 @@ void CClient::newGame( CConnection *con, StartInfo *si )
for(auto it = si->playerInfos.begin(); it != si->playerInfos.end(); ++it)
{
if((networkMode == SINGLE) //single - one client has all player
|| (networkMode != SINGLE && serv->connectionID == it->second.human) //multi - client has only "its players"
|| (networkMode == HOST && it->second.human == false)) //multi - host has all AI players
if((networkMode == SINGLE) //single - one client has all player
|| (networkMode != SINGLE && serv->connectionID == it->second.playerID) //multi - client has only "its players"
|| (networkMode == HOST && it->second.playerID == PlayerSettings::PLAYER_AI))//multi - host has all AI players
{
myPlayers.insert(it->first); //add player
}
@ -368,7 +368,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
if(si->mode != StartInfo::DUEL)
{
auto cb = make_shared<CCallback>(gs,color,this);
if(!it->second.human)
if(it->second.playerID == PlayerSettings::PLAYER_AI)
{
std::string AItoGive = settings["server"]["playerAI"].String();
if(!sensibleAILimit)

View File

@ -24,7 +24,6 @@ using namespace boost::assign;
*/
extern boost::rand48 ran;
extern Bonus * ParseBonus (const JsonVector &ability_vec);
const std::string & CArtifact::Name() const
{
@ -366,11 +365,11 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
auto ga = dynamic_cast <CGrowingArtifact *>(artifacts[artifact["id"].Float()].get());
BOOST_FOREACH (auto b, artifact["bonusesPerLevel"].Vector())
{
ga->bonusesPerLevel.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *ParseBonus (b["bonus"].Vector())));
ga->bonusesPerLevel.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"].Vector())));
}
BOOST_FOREACH (auto b, artifact["thresholdBonuses"].Vector())
{
ga->thresholdBonuses.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *ParseBonus (b["bonus"].Vector())));
ga->thresholdBonuses.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"].Vector())));
}
}
}
@ -614,7 +613,7 @@ void CArtHandler::addBonuses()
BOOST_FOREACH (auto b, artifact["bonuses"].Vector())
{
ga->addNewBonus(ParseBonus (b));
ga->addNewBonus(JsonUtils::parseBonus (b));
}
if(artifact["type"].String() == "Creature")
makeItCreatureArt(ga->id);

View File

@ -59,7 +59,7 @@ void SettingsStorage::init()
{
JsonNode(ResourceID("config/settings.json")).swap(config);
JsonNode schema(ResourceID("config/defaultSettings.json"));
config.validate(schema);
JsonUtils::validate(config, schema);
}
void SettingsStorage::invalidateNode(const std::vector<std::string> &changedPath)
@ -71,7 +71,7 @@ void SettingsStorage::invalidateNode(const std::vector<std::string> &changedPath
JsonNode schema(ResourceID("config/defaultSettings.json"));
savedConf.Struct().erase("session");
savedConf.minimize(schema);
JsonUtils::minimize(savedConf, schema);
CResourceHandler::get()->createResource("CONFIG/settings.json");

View File

@ -500,7 +500,7 @@ void CCreatureHandler::loadCreatures()
}
BOOST_FOREACH (auto bonus, config3["bonusPerLevel"].Vector())
{
commanderLevelPremy.push_back(ParseBonus (bonus.Vector()));
commanderLevelPremy.push_back(JsonUtils::parseBonus (bonus.Vector()));
}
int i = 0;
@ -517,7 +517,7 @@ void CCreatureHandler::loadCreatures()
BOOST_FOREACH (auto ability, config3["abilityRequirements"].Vector())
{
std::pair <Bonus, std::pair <ui8, ui8> > a;
a.first = *ParseBonus (ability["ability"].Vector());
a.first = *JsonUtils::parseBonus (ability["ability"].Vector());
a.second.first = ability["skills"].Vector()[0].Float();
a.second.second = ability["skills"].Vector()[1].Float();
skillRequirements.push_back (a);
@ -674,7 +674,7 @@ CCreature * CCreatureHandler::loadCreature(const JsonNode & node)
BOOST_FOREACH (const JsonNode &bonus, node["abilities"].Vector())
{
auto b = ParseBonus(bonus);
auto b = JsonUtils::parseBonus(bonus);
b->source = Bonus::CREATURE_ABILITY;
b->duration = Bonus::PERMANENT;
cre->addNewBonus(b);
@ -682,7 +682,7 @@ CCreature * CCreatureHandler::loadCreature(const JsonNode & node)
BOOST_FOREACH (const JsonNode &exp, node["stackExperience"].Vector())
{
auto bonus = ParseBonus (exp["bonus"]);
auto bonus = JsonUtils::parseBonus (exp["bonus"]);
bonus->source = Bonus::STACK_EXPERIENCE;
bonus->duration = Bonus::PERMANENT;
const JsonVector &values = exp["values"].Vector();

View File

@ -841,7 +841,7 @@ void CGameState::init(StartInfo * si)
for(auto it = scenarioOps->playerInfos.cbegin();
it != scenarioOps->playerInfos.cend(); ++it)
{
if(it->second.human)
if(it->second.playerID != PlayerSettings::PLAYER_AI)
ret.push_back(&it->second);
}
@ -996,7 +996,7 @@ void CGameState::init(StartInfo * si)
{
std::pair<TPlayerColor,PlayerState> ins(it->first,PlayerState());
ins.second.color=ins.first;
ins.second.human = it->second.human;
ins.second.human = it->second.playerID;
ins.second.team = map->players[ins.first].team;
teams[ins.second.team].id = ins.second.team;//init team
teams[ins.second.team].players.insert(ins.first);//add player to team
@ -1021,7 +1021,8 @@ void CGameState::init(StartInfo * si)
for(auto it = scenarioOps->playerInfos.begin(); it != scenarioOps->playerInfos.end(); ++it)
{
const PlayerInfo &p = map->players[it->first];
bool generateHero = (p.generateHeroAtMainTown || (it->second.human && campaignGiveHero)) && p.hasMainTown;
bool generateHero = (p.generateHeroAtMainTown ||
(it->second.playerID != PlayerSettings::PLAYER_AI && campaignGiveHero)) && p.hasMainTown;
if(generateHero && vstd::contains(scenarioOps->playerInfos, it->first))
{
int3 hpos = p.posOfMainTown;
@ -1041,7 +1042,6 @@ void CGameState::init(StartInfo * si)
}
}
/*************************replace hero placeholders*****************************/
tlog4 << "\tReplacing hero placeholders";
if (scenarioOps->campState)
@ -1301,14 +1301,14 @@ void CGameState::init(StartInfo * si)
for(auto k=players.begin(); k!=players.end(); ++k)
{
//starting bonus
if(scenarioOps->playerInfos[k->first].bonus==PlayerSettings::brandom)
if(scenarioOps->playerInfos[k->first].bonus==PlayerSettings::RANDOM)
scenarioOps->playerInfos[k->first].bonus = ran()%3;
switch(scenarioOps->playerInfos[k->first].bonus)
{
case PlayerSettings::bgold:
case PlayerSettings::GOLD:
k->second.resources[Res::GOLD] += 500 + (ran()%6)*100;
break;
case PlayerSettings::bresource:
case PlayerSettings::RESOURCE:
{
int res = VLC->townh->towns[scenarioOps->playerInfos[k->first].castle].primaryRes;
if(res == 127)
@ -1322,7 +1322,7 @@ void CGameState::init(StartInfo * si)
}
break;
}
case PlayerSettings::bartifact:
case PlayerSettings::ARTIFACT:
{
if(!k->second.heroes.size())
{

View File

@ -106,9 +106,9 @@ void CHeroHandler::loadObstacles()
obi.defName = obs["defname"].String();
obi.width = obs["width"].Float();
obi.height = obs["height"].Float();
obi.allowedTerrains = obs["allowedTerrain"].StdVector<ui8>();
obi.allowedSpecialBfields = obs["specialBattlefields"].StdVector<ui8>();
obi.blockedTiles = obs["blockedTiles"].StdVector<si16>();
obi.allowedTerrains = obs["allowedTerrain"].convertTo<std::vector<ui8> >();
obi.allowedSpecialBfields = obs["specialBattlefields"].convertTo<std::vector<ui8> >();
obi.blockedTiles = obs["blockedTiles"].convertTo<std::vector<si16> >();
obi.isAbsoluteObstacle = absolute;
}
};

View File

@ -5363,7 +5363,7 @@ void CGEvent::onHeroVisit( const CGHeroInstance * h ) const
{
if(!(availableFor & (1 << h->tempOwner)))
return;
if(cb->getPlayerSettings(h->tempOwner)->human)
if(cb->getPlayerSettings(h->tempOwner)->playerID)
{
if(humanActivate)
activated(h);

View File

@ -364,7 +364,7 @@ void CSpellHandler::loadSpells()
BOOST_FOREACH(const JsonNode &range, spell["ranges"].Vector())
s->range[idx++] = range.String();
s->counteredSpells = spell["counters"].StdVector<TSpell>();
s->counteredSpells = spell["counters"].convertTo<std::vector<TSpell> >();
}
//spell fixes

View File

@ -394,7 +394,7 @@ void CTownHandler::loadTown(CTown &town, const JsonNode & source)
town.mageLevel = source["mageGuild"].Float();
town.primaryRes = source["primaryResource"].Float();
town.warMachine = source["warMachine"].Float();
town.names = source["names"].StdVector<std::string>();
town.names = source["names"].convertTo<std::vector<std::string> >();
// Horde building creature level
BOOST_FOREACH(const JsonNode &node, source["horde"].Vector())
@ -515,7 +515,7 @@ void CTownHandler::load()
JsonNode & legacyBuilding = legacyBuildings[building["id"].Float()];
if (!legacyBuilding.isNull()) //merge if h3 config was found for this building
JsonNode::merge(building, legacyBuilding);
JsonUtils::merge(building, legacyBuilding);
}
}
}
@ -523,12 +523,12 @@ void CTownHandler::load()
load(buildingsConf);
}
std::set<ui32> CTownHandler::getDefaultAllowedFactions() const
std::set<TFaction> CTownHandler::getDefaultAllowedFactions() const
{
std::set<ui32> allowedFactions;
for(int i = 0; i <= 8; ++i)
std::set<TFaction> allowedFactions;
BOOST_FOREACH(auto town, towns)
{
allowedFactions.insert(i);
allowedFactions.insert(town.first);
}
return allowedFactions;
}

View File

@ -225,7 +225,7 @@ public:
*
* @return a list of allowed factions, the index which is unique is the faction id
*/
std::set<ui32> getDefaultAllowedFactions() const;
std::set<TFaction> getDefaultAllowedFactions() const;
template <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -4,7 +4,9 @@
#include "HeroBonus.h"
#include "Filesystem/CResourceLoader.h"
const JsonNode JsonNode::nullNode;
using namespace JsonDetail;
static const JsonNode nullNode;
JsonNode::JsonNode(JsonType Type):
type(DATA_NULL)
@ -99,16 +101,6 @@ bool JsonNode::operator != (const JsonNode &other) const
return !(*this == other);
}
void JsonNode::minimize(const JsonNode& schema)
{
JsonValidator validator(*this, schema, true);
}
void JsonNode::validate(const JsonNode& schema)
{
JsonValidator validator(*this, schema, false);
}
JsonNode::JsonType JsonNode::getType() const
{
return type;
@ -238,39 +230,6 @@ const JsonNode & JsonNode::operator[](std::string child) const
}
////////////////////////////////////////////////////////////////////////////////
void JsonNode::merge(JsonNode & dest, JsonNode & source)
{
switch (source.getType())
{
break; case DATA_NULL: dest.setType(DATA_NULL);
break; case DATA_BOOL: std::swap(dest.Bool(), source.Bool());
break; case DATA_FLOAT: std::swap(dest.Float(), source.Float());
break; case DATA_STRING: std::swap(dest.String(), source.String());
break; case DATA_VECTOR:
{
//reserve place and *move* data from source to dest
source.Vector().reserve(source.Vector().size() + dest.Vector().size());
std::move(source.Vector().begin(), source.Vector().end(),
std::back_inserter(dest.Vector()));
}
break; case DATA_STRUCT:
{
//recursively merge all entries from struct
BOOST_FOREACH(auto & node, source.Struct())
merge(dest[node.first], node.second);
}
}
}
void JsonNode::mergeCopy(JsonNode & dest, JsonNode source)
{
// uses copy created in stack to safely merge two nodes
merge(dest, source);
}
////////////////////////////////////////////////////////////////////////////////
template<typename Iterator>
void JsonWriter::writeContainer(Iterator begin, Iterator end)
{
@ -830,7 +789,7 @@ bool JsonValidator::validateProperties(JsonNode &node, const JsonNode &schema)
{
if (nodeIter->first < schemaIter->first) //No schema for entry
{
validateNode(nodeIter->second, JsonNode::nullNode, nodeIter->first);
validateNode(nodeIter->second, nullNode, nodeIter->first);
JsonMap::iterator toRemove = nodeIter++;
node.Struct().erase(toRemove);
@ -853,7 +812,7 @@ bool JsonValidator::validateProperties(JsonNode &node, const JsonNode &schema)
}
while (nodeIter != node.Struct().end())
{
validateNode(nodeIter->second, JsonNode::nullNode, nodeIter->first);
validateNode(nodeIter->second, nullNode, nodeIter->first);
JsonMap::iterator toRemove = nodeIter++;
node.Struct().erase(toRemove);
}
@ -910,7 +869,7 @@ JsonValidator::JsonValidator(JsonNode &root, const JsonNode &schema, bool Minimi
tlog3<<errors;
}
Bonus * ParseBonus (const JsonVector &ability_vec) //TODO: merge with AddAbility, create universal parser for all bonus properties
Bonus * JsonUtils::parseBonus (const JsonVector &ability_vec) //TODO: merge with AddAbility, create universal parser for all bonus properties
{
Bonus * b = new Bonus();
std::string type = ability_vec[0].String();
@ -950,7 +909,7 @@ const T & parseByMap(const std::map<std::string, T> & map, const JsonNode * val,
return defaultValue;
};
Bonus * ParseBonus (const JsonNode &ability)
Bonus * JsonUtils::parseBonus (const JsonNode &ability)
{
Bonus * b = new Bonus();
@ -1029,7 +988,7 @@ Key reverseMapFirst(const Val & val, const std::map<Key, Val> map)
return "";
}
DLL_LINKAGE void UnparseBonus( JsonNode &node, const Bonus * bonus )
void JsonUtils::unparseBonus( JsonNode &node, const Bonus * bonus )
{
node["type"].String() = reverseMapFirst<std::string, int>(bonus->type, bonusNameMap);
node["subtype"].Float() = bonus->subtype;
@ -1050,6 +1009,45 @@ DLL_LINKAGE void UnparseBonus( JsonNode &node, const Bonus * bonus )
{
node["propagator"].String() = reverseMapFirst<std::string, TPropagatorPtr>(bonus->propagator, bonusPropagatorMap);
}
}
void JsonUtils::minimize(JsonNode & node, const JsonNode& schema)
{
JsonValidator validator(node, schema, true);
}
void JsonUtils::validate(JsonNode & node, const JsonNode& schema)
{
JsonValidator validator(node, schema, false);
}
void JsonUtils::merge(JsonNode & dest, JsonNode & source)
{
switch (source.getType())
{
break; case JsonNode::DATA_NULL: dest.setType(JsonNode::DATA_NULL);
break; case JsonNode::DATA_BOOL: std::swap(dest.Bool(), source.Bool());
break; case JsonNode::DATA_FLOAT: std::swap(dest.Float(), source.Float());
break; case JsonNode::DATA_STRING: std::swap(dest.String(), source.String());
break; case JsonNode::DATA_VECTOR:
{
//reserve place and *move* data from source to dest
source.Vector().reserve(source.Vector().size() + dest.Vector().size());
std::move(source.Vector().begin(), source.Vector().end(),
std::back_inserter(dest.Vector()));
}
break; case JsonNode::DATA_STRUCT:
{
//recursively merge all entries from struct
BOOST_FOREACH(auto & node, source.Struct())
merge(dest[node.first], node.second);
}
}
}
void JsonUtils::mergeCopy(JsonNode & dest, JsonNode source)
{
// uses copy created in stack to safely merge two nodes
merge(dest, source);
}

View File

@ -53,11 +53,6 @@ public:
bool operator == (const JsonNode &other) const;
bool operator != (const JsonNode &other) const;
//removes all nodes that are identical to default entry in schema
void minimize(const JsonNode& schema);
//check schema
void validate(const JsonNode& schema);
//Convert node to another type. Converting to NULL will clear all data
void setType(JsonType Type);
JsonType getType() const;
@ -78,29 +73,19 @@ public:
const JsonVector & Vector() const;
const JsonMap & Struct() const;
template<typename T>
std::vector<T> StdVector() const;
/// convert json tree into specified type. Json tree must have same type as Type
/// Valid types: bool, string, any numeric, map and vector
/// example: convertTo< std::map< std::vector<int> > >();
template<typename Type>
Type convertTo() const;
//operator [], for structs only - get child node by name
JsonNode & operator[](std::string child);
const JsonNode & operator[](std::string child) const;
//error value for const operator[]
static const JsonNode nullNode;
/// recursivly merges source into dest, replacing identical fields
/// struct : recursively calls this function
/// arrays : append array in dest with data from source
/// values : value in source will replace value in dest
/// null : if value in source is present but set to null it will delete entry in dest
/// this function will destroy data in source
static void merge(JsonNode & dest, JsonNode & source);
/// this function will preserve data stored in source by creating copy
static void mergeCopy(JsonNode & dest, JsonNode source);
template <typename Handler> void serialize(Handler &h, const int version)
{
// simple saving - save json in its string interpretation
if (h.saving)
{
std::ostringstream stream;
@ -117,129 +102,199 @@ public:
}
};
template<>
inline std::vector<std::string> JsonNode::StdVector() const
namespace JsonUtils
{
std::vector<std::string> ret;
BOOST_FOREACH(const JsonNode &node, Vector())
{
ret.push_back(node.String());
}
return ret;
DLL_LINKAGE Bonus * parseBonus (const JsonVector &ability_vec);
DLL_LINKAGE Bonus * parseBonus (const JsonNode &bonus);
DLL_LINKAGE void unparseBonus (JsonNode &node, const Bonus * bonus);
/// recursivly merges source into dest, replacing identical fields
/// struct : recursively calls this function
/// arrays : append array in dest with data from source
/// values : value in source will replace value in dest
/// null : if value in source is present but set to null it will delete entry in dest
/// this function will destroy data in source
DLL_LINKAGE void merge(JsonNode & dest, JsonNode & source);
/// this function will preserve data stored in source by creating copy
DLL_LINKAGE void mergeCopy(JsonNode & dest, JsonNode source);
/// removes all nodes that are identical to default entry in schema
DLL_LINKAGE void minimize(JsonNode & node, const JsonNode& schema);
/// check schema
DLL_LINKAGE void validate(JsonNode & node, const JsonNode& schema);
}
template<typename T>
std::vector<T> JsonNode::StdVector() const
//////////////////////////////////////////////////////////////////////////////////////////////////////
// End of public section of the file. Anything below should be only used internally in JsonNode.cpp //
//////////////////////////////////////////////////////////////////////////////////////////////////////
namespace JsonDetail
{
static_assert(std::is_arithmetic<T>::value, "This works with numbers only.");
std::vector<T> ret;
BOOST_FOREACH(const JsonNode &node, Vector())
// convertion helpers for JsonNode::convertTo (partial template function instantiation is illegal in c++)
template<typename Type>
struct JsonConverter
{
ret.push_back(node.Float());
}
return ret;
}
class JsonWriter
{
//prefix for each line (tabulation)
std::string prefix;
std::ostream &out;
public:
template<typename Iterator>
void writeContainer(Iterator begin, Iterator end);
void writeEntry(JsonMap::const_iterator entry);
void writeEntry(JsonVector::const_iterator entry);
void writeString(const std::string &string);
void writeNode(const JsonNode &node);
JsonWriter(std::ostream &output, const JsonNode &node);
};
//Tiny string class that uses const char* as data for speed, members are private
//for ease of debugging and some compatibility with std::string
class constString
{
const char *data;
const size_t datasize;
public:
constString(const char * inputString, size_t stringSize):
data(inputString),
datasize(stringSize)
{
}
inline size_t size() const
{
return datasize;
static Type convert(const JsonNode & node)
{
///this should be triggered only for numeric types
static_assert(std::is_arithmetic<Type>::value, "Unsupported type for JsonNode::convertTo()!");
return node.Float();
}
};
inline const char& operator[] (size_t position)
template<typename Type>
struct JsonConverter<std::map<std::string, Type> >
{
assert (position < datasize);
return data[position];
}
};
static std::map<std::string, Type> convert(const JsonNode & node)
{
std::map<std::string, Type> ret;
BOOST_FOREACH(auto entry, node.Struct())
{
ret.insert(entry.first, entry.second.convertTo<Type>());
}
return ret;
//Internal class for string -> JsonNode conversion
class JsonParser
}
};
template<typename Type>
struct JsonConverter<std::vector<Type> >
{
static std::vector<Type> convert(const JsonNode & node)
{
std::vector<Type> ret;
BOOST_FOREACH(auto entry, node.Vector())
{
ret.push_back(entry.convertTo<Type>());
}
return ret;
}
};
template<>
struct JsonConverter<std::string>
{
static std::string convert(const JsonNode & node)
{
return node.String();
}
};
template<>
struct JsonConverter<bool>
{
static bool convert(const JsonNode & node)
{
return node.Bool();
}
};
class JsonWriter
{
//prefix for each line (tabulation)
std::string prefix;
std::ostream &out;
public:
template<typename Iterator>
void writeContainer(Iterator begin, Iterator end);
void writeEntry(JsonMap::const_iterator entry);
void writeEntry(JsonVector::const_iterator entry);
void writeString(const std::string &string);
void writeNode(const JsonNode &node);
JsonWriter(std::ostream &output, const JsonNode &node);
};
//Tiny string class that uses const char* as data for speed, members are private
//for ease of debugging and some compatibility with std::string
class constString
{
const char *data;
const size_t datasize;
public:
constString(const char * inputString, size_t stringSize):
data(inputString),
datasize(stringSize)
{
}
inline size_t size() const
{
return datasize;
};
inline const char& operator[] (size_t position)
{
assert (position < datasize);
return data[position];
}
};
//Internal class for string -> JsonNode conversion
class JsonParser
{
std::string errors; // Contains description of all encountered errors
constString input; // Input data
ui32 lineCount; // Currently parsed line, starting from 1
size_t lineStart; // Position of current line start
size_t pos; // Current position of parser
//Helpers
bool extractEscaping(std::string &str);
bool extractLiteral(const std::string &literal);
bool extractString(std::string &string);
bool extractWhitespace(bool verbose = true);
bool extractSeparator();
bool extractElement(JsonNode &node, char terminator);
//Methods for extracting JSON data
bool extractArray(JsonNode &node);
bool extractFalse(JsonNode &node);
bool extractFloat(JsonNode &node);
bool extractNull(JsonNode &node);
bool extractString(JsonNode &node);
bool extractStruct(JsonNode &node);
bool extractTrue(JsonNode &node);
bool extractValue(JsonNode &node);
//Add error\warning message to list
bool error(const std::string &message, bool warning=false);
public:
JsonParser(const char * inputString, size_t stringSize, JsonNode &root);
};
//Internal class for Json validation, used automaticaly in JsonNode constructor. Behaviour:
// - "schema" entry from root node is used for validation and will be removed
// - any missing entries will be replaced with default value from schema (if present)
// - if entry uses different type than defined in schema it will be removed
// - entries nod described in schema will be kept unchanged
class JsonValidator
{
std::string errors; // Contains description of all encountered errors
std::list<std::string> currentPath; // path from root node to current one
bool minimize;
bool validateType(JsonNode &node, const JsonNode &schema, JsonNode::JsonType type);
bool validateSchema(JsonNode::JsonType &type, const JsonNode &schema);
bool validateNode(JsonNode &node, const JsonNode &schema, const std::string &name);
bool validateItems(JsonNode &node, const JsonNode &schema);
bool validateProperties(JsonNode &node, const JsonNode &schema);
bool addMessage(const std::string &message);
public:
// validate node with "schema" entry
JsonValidator(JsonNode &root, bool minimize=false);
// validate with external schema
JsonValidator(JsonNode &root, const JsonNode &schema, bool minimize=false);
};
} // namespace JsonDetail
template<typename Type>
Type JsonNode::convertTo() const
{
std::string errors; // Contains description of all encountered errors
constString input; // Input data
ui32 lineCount; // Currently parsed line, starting from 1
size_t lineStart; // Position of current line start
size_t pos; // Current position of parser
//Helpers
bool extractEscaping(std::string &str);
bool extractLiteral(const std::string &literal);
bool extractString(std::string &string);
bool extractWhitespace(bool verbose = true);
bool extractSeparator();
bool extractElement(JsonNode &node, char terminator);
//Methods for extracting JSON data
bool extractArray(JsonNode &node);
bool extractFalse(JsonNode &node);
bool extractFloat(JsonNode &node);
bool extractNull(JsonNode &node);
bool extractString(JsonNode &node);
bool extractStruct(JsonNode &node);
bool extractTrue(JsonNode &node);
bool extractValue(JsonNode &node);
//Add error\warning message to list
bool error(const std::string &message, bool warning=false);
public:
JsonParser(const char * inputString, size_t stringSize, JsonNode &root);
};
//Internal class for Json validation, used automaticaly in JsonNode constructor. Behaviour:
// - "schema" entry from root node is used for validation and will be removed
// - any missing entries will be replaced with default value from schema (if present)
// - if entry uses different type than defined in schema it will be removed
// - entries nod described in schema will be kept unchanged
class JsonValidator
{
std::string errors; // Contains description of all encountered errors
std::list<std::string> currentPath; // path from root node to current one
bool minimize;
bool validateType(JsonNode &node, const JsonNode &schema, JsonNode::JsonType type);
bool validateSchema(JsonNode::JsonType &type, const JsonNode &schema);
bool validateNode(JsonNode &node, const JsonNode &schema, const std::string &name);
bool validateItems(JsonNode &node, const JsonNode &schema);
bool validateProperties(JsonNode &node, const JsonNode &schema);
bool addMessage(const std::string &message);
public:
// validate node with "schema" entry
JsonValidator(JsonNode &root, bool minimize=false);
// validate with external schema
JsonValidator(JsonNode &root, const JsonNode &schema, bool minimize=false);
};
DLL_LINKAGE Bonus * ParseBonus (const JsonVector &ability_vec);
DLL_LINKAGE Bonus * ParseBonus (const JsonNode &bonus);
DLL_LINKAGE void UnparseBonus (JsonNode &node, const Bonus * bonus);
return JsonDetail::JsonConverter<Type>::convert(*this);
}

View File

@ -102,7 +102,7 @@ struct DLL_LINKAGE PlayerInfo
EAiTactic::EAiTactic aiTactic;
/** A list of unique IDs of allowed factions. */
std::set<ui32> allowedFactions;
std::set<TFaction> allowedFactions;
/** Unused. True if the faction should be chosen randomly. */
bool isFactionRandom;

View File

@ -25,7 +25,7 @@ void CMapInfo::countPlayers()
if(scenarioOpts)
for (auto i = scenarioOpts->playerInfos.cbegin(); i != scenarioOpts->playerInfos.cend(); i++)
if(i->second.human)
if(i->second.playerID != PlayerSettings::PLAYER_AI)
actualHumanPlayers++;
}

View File

@ -19,19 +19,31 @@ class CCampaignState;
/// Struct which describes the name, the color, the starting bonus of a player
struct PlayerSettings
{
enum Ebonus {brandom=-1,bartifact, bgold, bresource};
enum { PLAYER_AI = 0 }; // for use in playerID
enum Ebonus {
NONE = -2,
RANDOM = -1,
ARTIFACT = 0,
GOLD = 1,
RESOURCE = 2
};
//uses enum type Ebonus
si8 bonus;
si16 castle;
si32 hero,
heroPortrait; //-1 if default, else ID
si32 castle, hero, //ID, if -1 then random, if -2 then none
heroPortrait; //-1 if default, else ID
std::string heroName;
si8 bonus; //uses enum type Ebonus
TPlayerColor color; //from 0 -
ui8 handicap;//0-no, 1-mild, 2-severe
ui8 team;
std::string name;
ui8 human; //0 - AI, non-0 serves as player id
template <typename Handler> void serialize(Handler &h, const int version)
ui8 playerID; //0 - AI, non-0 serves as player id
template <typename Handler>
void serialize(Handler &h, const int version)
{
h & castle;
h & hero;
@ -41,13 +53,13 @@ struct PlayerSettings
h & color;
h & handicap;
h & name;
h & human;
h & playerID;
h & team;
}
PlayerSettings()
{
bonus = brandom;
bonus = RANDOM;
castle = -2;
heroPortrait = -1;
}
@ -85,13 +97,14 @@ struct StartInfo
PlayerSettings *getPlayersSettings(const ui8 nameID)
{
for(auto it=playerInfos.begin(); it != playerInfos.end(); ++it)
if(it->second.human == nameID)
if(it->second.playerID == nameID)
return &it->second;
return NULL;
}
template <typename Handler> void serialize(Handler &h, const int version)
template <typename Handler>
void serialize(Handler &h, const int version)
{
h & mode;
h & difficulty;