载入中...
搜索中...
未找到
TagStore.cpp
浏览该文件的文档.
1#include "tags/TagStore.h"
2
3#include <algorithm>
4#include <utility>
5
6namespace eve::tags {
7
8std::vector<std::string> TagStore::values(const ValueSet* set) {
9 return set ? std::vector<std::string>(set->begin(), set->end()) : std::vector<std::string>{};
10}
11
12bool TagStore::requireAll(const ValueSet* held, const std::vector<std::string>& requested) {
13 return std::all_of(requested.begin(), requested.end(),
14 [held](const auto& value) { return held && held->contains(value); });
15}
16
17bool TagStore::requireAny(const ValueSet* held, const std::vector<std::string>& requested) {
18 return held &&
19 std::any_of(requested.begin(), requested.end(), [held](const auto& value) { return held->contains(value); });
20}
21
22void TagStore::emit(std::string action, SubjectId subject, std::string value) {
23 events_.push_back({nextSequence_++, std::move(action), std::move(subject), std::move(value)});
24}
25
26bool TagStore::mutate(std::map<SubjectId, ValueSet>& valuesBySubject, Index* reverse, const SubjectId& subject,
27 const std::string& value, bool add, const char* addedAction, const char* removedAction) {
28 if (subject.empty() || value.empty()) return false;
29 auto found = valuesBySubject.find(subject);
30 if (add) {
31 auto& values = valuesBySubject[subject];
32 if (!values.insert(value).second) return false;
33 if (reverse) (*reverse)[value].insert(subject);
34 emit(addedAction, subject, value);
35 return true;
36 }
37 if (found == valuesBySubject.end() || found->second.erase(value) == 0) return false;
38 if (found->second.empty()) valuesBySubject.erase(found);
39 if (reverse) {
40 auto indexed = reverse->find(value);
41 if (indexed != reverse->end()) {
42 indexed->second.erase(subject);
43 if (indexed->second.empty()) reverse->erase(indexed);
44 }
45 }
46 emit(removedAction, subject, value);
47 return true;
48}
49
50bool TagStore::addTag(const SubjectId& subject, const std::string& tag) {
51 return mutate(tags_, &subjectsByTag_, subject, tag, true, "tag_added", "tag_removed");
52}
53bool TagStore::removeTag(const SubjectId& subject, const std::string& tag) {
54 return mutate(tags_, &subjectsByTag_, subject, tag, false, "tag_added", "tag_removed");
55}
56bool TagStore::hasTag(const SubjectId& subject, const std::string& tag) const {
57 const auto found = tags_.find(subject);
58 return found != tags_.end() && found->second.contains(tag);
59}
60bool TagStore::hasTagMatching(const SubjectId& subject, const std::string& tag, GameplayTagMatch match) const {
61 const auto found = tags_.find(subject);
62 return found != tags_.end() && std::any_of(found->second.begin(), found->second.end(), [&](const auto& held) {
63 return gameplayTagMatches(held, tag, match);
64 });
65}
66std::vector<std::string> TagStore::tagsOf(const SubjectId& subject) const {
67 const auto found = tags_.find(subject);
68 return values(found == tags_.end() ? nullptr : &found->second);
69}
70std::vector<SubjectId> TagStore::subjectsWithTag(const std::string& tag) const {
71 const auto found = subjectsByTag_.find(tag);
72 return found == subjectsByTag_.end() ? std::vector<SubjectId>{}
73 : std::vector<SubjectId>(found->second.begin(), found->second.end());
74}
75std::vector<SubjectId> TagStore::subjectsWithTagMatching(const std::string& tag, GameplayTagMatch match) const {
76 if (match == GameplayTagMatch::Exact) return subjectsWithTag(tag);
77 std::set<SubjectId> matches;
78 for (const auto& [held, subjects] : subjectsByTag_)
79 if (gameplayTagMatches(held, tag, match)) matches.insert(subjects.begin(), subjects.end());
80 return {matches.begin(), matches.end()};
81}
82bool TagStore::requireAllTags(const SubjectId& subject, const std::vector<std::string>& requested) const {
83 const auto found = tags_.find(subject);
84 return requireAll(found == tags_.end() ? nullptr : &found->second, requested);
85}
86bool TagStore::requireAnyTag(const SubjectId& subject, const std::vector<std::string>& requested) const {
87 const auto found = tags_.find(subject);
88 return requireAny(found == tags_.end() ? nullptr : &found->second, requested);
89}
90bool TagStore::matchesAllTags(const SubjectId& subject, const std::vector<std::string>& requested,
91 GameplayTagMatch match) const {
92 return std::all_of(requested.begin(), requested.end(),
93 [&](const auto& query) { return hasTagMatching(subject, query, match); });
94}
95bool TagStore::matchesAnyTag(const SubjectId& subject, const std::vector<std::string>& requested,
96 GameplayTagMatch match) const {
97 return std::any_of(requested.begin(), requested.end(),
98 [&](const auto& query) { return hasTagMatching(subject, query, match); });
99}
100
101bool TagStore::addCapability(const SubjectId& subject, const std::string& capability) {
102 return mutate(capabilities_, nullptr, subject, capability, true, "capability_added", "capability_removed");
103}
104bool TagStore::removeCapability(const SubjectId& subject, const std::string& capability) {
105 return mutate(capabilities_, nullptr, subject, capability, false, "capability_added", "capability_removed");
106}
107bool TagStore::hasCapability(const SubjectId& subject, const std::string& capability) const {
108 const auto found = capabilities_.find(subject);
109 return found != capabilities_.end() && found->second.contains(capability);
110}
111std::vector<std::string> TagStore::capabilitiesOf(const SubjectId& subject) const {
112 const auto found = capabilities_.find(subject);
113 return values(found == capabilities_.end() ? nullptr : &found->second);
114}
115bool TagStore::requireAllCapabilities(const SubjectId& subject, const std::vector<std::string>& requested) const {
116 const auto found = capabilities_.find(subject);
117 return requireAll(found == capabilities_.end() ? nullptr : &found->second, requested);
118}
119bool TagStore::requireAnyCapability(const SubjectId& subject, const std::vector<std::string>& requested) const {
120 const auto found = capabilities_.find(subject);
121 return requireAny(found == capabilities_.end() ? nullptr : &found->second, requested);
122}
123
124bool TagStore::removeSubject(const SubjectId& subject) {
125 const auto tags = tagsOf(subject);
126 const auto capabilities = capabilitiesOf(subject);
127 for (const auto& tag : tags) removeTag(subject, tag);
128 for (const auto& capability : capabilities) removeCapability(subject, capability);
129 if (tags.empty() && capabilities.empty()) return false;
130 emit("subject_removed", subject, {});
131 return true;
132}
133
134void TagStore::clear() {
135 tags_.clear();
136 capabilities_.clear();
137 subjectsByTag_.clear();
138 events_.clear();
139 nextSequence_ = 1;
140}
141
142} // namespace eve::tags
double value
int subject
Definition AnimSmr.cpp:163
std::map< std::string, Var > values
const std::string * tag
std::string action
Definition PlayHost.cpp:117
bool found
std::string string
bool gameplayTagMatches(std::string_view candidate, std::string_view query, GameplayTagMatch match) noexcept
Tests exact or dot-boundary descendant membership.
GameplayTagMatch
Selects exact or hierarchical descendant matching.
Definition GameplayTag.h:23
std::string SubjectId
Stable, game-defined identifier for an object carrying tags.
Definition TagStore.h:16