1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
/*
* CBonusSystemNode.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "BonusList.h"
#include "IBonusBearer.h"
#include "../serializer/Serializeable.h"
#include <tbb/concurrent_hash_map.h>
VCMI_LIB_NAMESPACE_BEGIN
using TNodes = std::set<CBonusSystemNode *>;
using TCNodes = std::set<const CBonusSystemNode *>;
using TNodesVector = std::vector<CBonusSystemNode *>;
using TCNodesVector = std::vector<const CBonusSystemNode *>;
class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer, public virtual Serializeable, public boost::noncopyable
{
public:
enum ENodeTypes
{
NONE = -1,
UNKNOWN, STACK_INSTANCE, STACK_BATTLE, SPECIALTY, ARTIFACT, CREATURE, ARTIFACT_INSTANCE, HERO, PLAYER, TEAM,
TOWN_AND_VISITOR, BATTLE, COMMANDER, GLOBAL_EFFECTS, ALL_CREATURES, TOWN
};
struct HashStringCompare {
static size_t hash(const std::string& data)
{
std::hash<std::string> hasher;
return hasher(data);
}
static bool equal(const std::string& x, const std::string& y)
{
return x == y;
}
};
private:
BonusList bonuses; //wielded bonuses (local or up-propagated here)
BonusList exportedBonuses; //bonuses coming from this node (wielded or propagated away)
TCNodesVector parentsToInherit; // we inherit bonuses from them
TNodesVector parentsToPropagate; // we may attach our bonuses to them
TNodesVector children;
ENodeTypes nodeType;
bool isHypotheticNode;
mutable BonusList cachedBonuses;
mutable int32_t cachedLast;
std::atomic<int32_t> nodeChanged;
void invalidateChildrenNodes(int32_t changeCounter);
// Setting a value to cachingStr before getting any bonuses caches the result for later requests.
// This string needs to be unique, that's why it has to be set in the following manner:
// [property key]_[value] => only for selector
using RequestsMap = tbb::concurrent_hash_map<std::string, std::pair<int32_t, TBonusListPtr>, HashStringCompare>;
mutable RequestsMap cachedRequests;
mutable std::shared_mutex sync;
void getAllBonusesRec(BonusList &out, const CSelector & selector) const;
TConstBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit) const;
std::shared_ptr<Bonus> getUpdatedBonus(const std::shared_ptr<Bonus> & b, const TUpdaterPtr & updater) const;
void limitBonuses(const BonusList &allBonuses, BonusList &out) const; //out will bo populed with bonuses that are not limited here
void getRedParents(TCNodes &out) const; //retrieves list of red parent nodes (nodes bonuses propagate from)
void getRedAncestors(TCNodes &out) const;
void getRedChildren(TNodes &out);
void getAllParents(TCNodes & out) const;
void propagateBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & source);
void unpropagateBonus(const std::shared_ptr<Bonus> & b);
bool actsAsBonusSourceOnly() const;
void newRedDescendant(CBonusSystemNode & descendant) const; //propagation needed
void removedRedDescendant(CBonusSystemNode & descendant) const; //de-propagation needed
std::string nodeShortInfo() const;
void exportBonus(const std::shared_ptr<Bonus> & b);
protected:
bool isIndependentNode() const; //node is independent when it has no parents nor children
void exportBonuses();
public:
explicit CBonusSystemNode(bool isHypotetic = false);
explicit CBonusSystemNode(ENodeTypes NodeType);
virtual ~CBonusSystemNode();
TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const override;
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
/// Returns first bonus matching selector
std::shared_ptr<const Bonus> getFirstBonus(const CSelector & selector) const;
/// Provides write access to first bonus from this node that matches selector
std::shared_ptr<Bonus> getLocalBonus(const CSelector & selector);
void attachTo(CBonusSystemNode & parent);
void attachToSource(const CBonusSystemNode & parent);
void detachFrom(CBonusSystemNode & parent);
void detachFromSource(const CBonusSystemNode & parent);
void detachFromAll();
virtual void addNewBonus(const std::shared_ptr<Bonus>& b);
void accumulateBonus(const std::shared_ptr<Bonus>& b); //add value of bonus with same type/subtype or create new
void removeBonus(const std::shared_ptr<Bonus>& b);
void removeBonuses(const CSelector & selector);
void removeBonusesRecursive(const CSelector & s);
///updates count of remaining turns and removes outdated bonuses by selector
void reduceBonusDurations(const CSelector &s);
virtual std::string bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const {return "";}; //description or bonus name
virtual std::string nodeName() const;
bool isHypothetic() const { return isHypotheticNode; }
void deserializationFix();
BonusList & getExportedBonusList();
const BonusList & getExportedBonusList() const;
CBonusSystemNode::ENodeTypes getNodeType() const;
void setNodeType(CBonusSystemNode::ENodeTypes type);
const TCNodesVector & getParentNodes() const;
void nodeHasChanged();
int32_t getTreeVersion() const override;
virtual PlayerColor getOwner() const
{
return PlayerColor::NEUTRAL;
}
template <typename Handler> void serialize(Handler &h)
{
h & nodeType;
h & exportedBonuses;
BONUS_TREE_DESERIALIZATION_FIX
}
friend class CBonusProxy;
};
VCMI_LIB_NAMESPACE_END
|