载入中...
搜索中...
未找到
SocialGraph.cpp
浏览该文件的文档.
2
3#include <algorithm>
4
5namespace eve::social {
6namespace {
7
8bool valid(const EntityId& id) { return !id.empty(); }
9
10template <typename Index, typename Key>
11void eraseIndex(Index& index, const Key& key, const EntityId& value) {
12 const auto found = index.find(key);
13 if (found == index.end()) return;
14 found->second.erase(value);
15 if (found->second.empty()) index.erase(found);
16}
17
18} // namespace
19
20EntityId SocialGraph::integerId(std::int64_t id) { return "#" + std::to_string(id); }
21
22void SocialGraph::emit(std::string action, EntityId source, EntityId target, std::string type, double oldValue,
23 double newValue) {
24 events_.push_back({nextSequence_++, std::move(action), std::move(source), std::move(target), std::move(type),
25 oldValue, newValue});
26}
27
28std::vector<EntityId> SocialGraph::values(const EntitySet* set) {
29 std::vector<EntityId> result;
30 if (!set) return result;
31 result.reserve(set->size());
32 for (const auto& [id, ignored] : *set) result.push_back(id);
33 return result;
34}
35
36bool SocialGraph::setOwner(const EntityId& entity, const EntityId& owner) {
37 if (!valid(entity)) return false;
38 const EntityId old = ownerOf(entity);
39 if (old == owner) return false;
40 if (!old.empty()) eraseIndex(owned_, old, entity);
41 if (owner.empty())
42 owners_.erase(entity);
43 else {
44 owners_[entity] = owner;
45 owned_[owner][entity] = true;
46 }
47 emit("owner_changed", entity, owner, {}, 0.0, 0.0);
48 return true;
49}
50
52 const auto found = owners_.find(entity);
53 return found == owners_.end() ? EntityId{} : found->second;
54}
55
56std::vector<EntityId> SocialGraph::ownedBy(const EntityId& owner) const {
57 const auto found = owned_.find(owner);
58 return values(found == owned_.end() ? nullptr : &found->second);
59}
60
61bool SocialGraph::setController(const EntityId& entity, const EntityId& controller) {
62 if (!valid(entity)) return false;
63 const EntityId old = controllerOf(entity);
64 if (old == controller) return false;
65 if (!old.empty()) eraseIndex(controlled_, old, entity);
66 if (controller.empty())
67 controllers_.erase(entity);
68 else {
69 controllers_[entity] = controller;
70 controlled_[controller][entity] = true;
71 }
72 emit("controller_changed", entity, controller);
73 return true;
74}
75
77 const auto found = controllers_.find(entity);
78 return found == controllers_.end() ? EntityId{} : found->second;
79}
80
81std::vector<EntityId> SocialGraph::controlledBy(const EntityId& controller) const {
82 const auto found = controlled_.find(controller);
83 return values(found == controlled_.end() ? nullptr : &found->second);
84}
85
86bool SocialGraph::assign(const EntityId& source, const std::string& role, const EntityId& target) {
87 if (!valid(source) || !valid(target) || role.empty()) return false;
88 auto& targets = assignmentTargets_[{source, role}];
89 if (targets.contains(target)) return false;
90 targets[target] = true;
91 assignmentSources_[{target, role}][source] = true;
92 emit("assignment_added", source, target, role);
93 return true;
94}
95
96bool SocialGraph::unassign(const EntityId& source, const std::string& role, const EntityId& target) {
97 const PairKey forward{source, role};
98 const auto found = assignmentTargets_.find(forward);
99 if (found == assignmentTargets_.end() || !found->second.contains(target)) return false;
100 eraseIndex(assignmentTargets_, forward, target);
101 eraseIndex(assignmentSources_, PairKey{target, role}, source);
102 emit("assignment_removed", source, target, role);
103 return true;
104}
105
106bool SocialGraph::isAssigned(const EntityId& source, const std::string& role, const EntityId& target) const {
107 const auto found = assignmentTargets_.find({source, role});
108 return found != assignmentTargets_.end() && found->second.contains(target);
109}
110
111std::vector<EntityId> SocialGraph::targetsOf(const EntityId& source, const std::string& role) const {
112 const auto found = assignmentTargets_.find({source, role});
113 return values(found == assignmentTargets_.end() ? nullptr : &found->second);
114}
115
116std::vector<EntityId> SocialGraph::assigneesOf(const EntityId& target, const std::string& role) const {
117 const auto found = assignmentSources_.find({target, role});
118 return values(found == assignmentSources_.end() ? nullptr : &found->second);
119}
120
121bool SocialGraph::setRelation(const EntityId& source, const EntityId& target, const std::string& type, double value) {
122 if (!valid(source) || !valid(target) || type.empty()) return false;
123 const EdgeKey key{source, target, type};
124 const auto found = relations_.find(key);
125 if (found != relations_.end() && found->second == value) return false;
126 const double old = found == relations_.end() ? 0.0 : found->second;
127 relations_[key] = value;
128 relationTargets_[{source, type}][target] = true;
129 relationSources_[{target, type}][source] = true;
130 emit(found == relations_.end() ? "relation_added" : "relation_changed", source, target, type, old, value);
131 return true;
132}
133
134double SocialGraph::addRelation(const EntityId& source, const EntityId& target, const std::string& type, double delta) {
135 const double value = relation(source, target, type) + delta;
137 return value;
138}
139
140bool SocialGraph::link(const EntityId& source, const EntityId& target, const std::string& type) {
141 return setRelation(source, target, type, 1.0);
142}
143
144bool SocialGraph::removeRelation(const EntityId& source, const EntityId& target, const std::string& type) {
145 const EdgeKey key{source, target, type};
146 const auto found = relations_.find(key);
147 if (found == relations_.end()) return false;
148 const double old = found->second;
149 relations_.erase(found);
150 eraseIndex(relationTargets_, PairKey{source, type}, target);
151 eraseIndex(relationSources_, PairKey{target, type}, source);
152 emit("relation_removed", source, target, type, old, 0.0);
153 return true;
154}
155
156bool SocialGraph::hasRelation(const EntityId& source, const EntityId& target, const std::string& type) const {
157 return relations_.contains({source, target, type});
158}
159
160double SocialGraph::relation(const EntityId& source, const EntityId& target, const std::string& type,
161 double fallback) const {
162 const auto found = relations_.find({source, target, type});
163 return found == relations_.end() ? fallback : found->second;
164}
165
166std::vector<EntityId> SocialGraph::relationTargets(const EntityId& source, const std::string& type,
167 double minimum) const {
168 std::vector<EntityId> result;
169 const auto found = relationTargets_.find({source, type});
170 if (found == relationTargets_.end()) return result;
171 for (const auto& [target, ignored] : found->second) {
172 if (relation(source, target, type) >= minimum) result.push_back(target);
173 }
174 return result;
175}
176
177std::vector<EntityId> SocialGraph::relationSources(const EntityId& target, const std::string& type,
178 double minimum) const {
179 std::vector<EntityId> result;
180 const auto found = relationSources_.find({target, type});
181 if (found == relationSources_.end()) return result;
182 for (const auto& [source, ignored] : found->second) {
183 if (relation(source, target, type) >= minimum) result.push_back(source);
184 }
185 return result;
186}
187
189 if (!valid(entity)) return false;
190 bool changed = setOwner(entity, {}) | setController(entity, {});
191
192 const auto owned = ownedBy(entity);
193 for (const auto& child : owned) changed = setOwner(child, {}) || changed;
194 const auto controlled = controlledBy(entity);
195 for (const auto& child : controlled) changed = setController(child, {}) || changed;
196
197 std::vector<std::tuple<EntityId, std::string, EntityId>> assignments;
198 for (const auto& [key, targets] : assignmentTargets_) {
199 for (const auto& [target, ignored] : targets) {
200 if (key.first == entity || target == entity) assignments.emplace_back(key.first, key.second, target);
201 }
202 }
203 for (const auto& [source, role, target] : assignments) changed = unassign(source, role, target) || changed;
204
205 std::vector<EdgeKey> relations;
206 for (const auto& [key, value] : relations_) {
207 if (std::get<0>(key) == entity || std::get<1>(key) == entity) relations.push_back(key);
208 }
209 for (const auto& [source, target, type] : relations) changed = removeRelation(source, target, type) || changed;
210
211 if (changed) emit("entity_removed", entity);
212 return changed;
213}
214
216 owners_.clear();
217 owned_.clear();
218 controllers_.clear();
219 controlled_.clear();
220 assignmentTargets_.clear();
221 assignmentSources_.clear();
222 relations_.clear();
223 relationTargets_.clear();
224 relationSources_.clear();
225 events_.clear();
226 nextSequence_ = 1;
227}
228
229} // namespace eve::social
LogicalId target
double value
ActiveSource owned
std::map< std::string, Var > values
float minimum[3]
std::uint32_t key
bool valid
std::string id
Definition PlayHost.cpp:108
bool found
uint32_t index
const UnitySourceAsset & source
bool assign(const EntityId &source, const std::string &role, const EntityId &target)
Adds a role-based source-to-target assignment.
EntityId controllerOf(const EntityId &entity) const
Returns an entity's controller, or an empty string when absent.
bool link(const EntityId &source, const EntityId &target, const std::string &type)
Creates a directed typed relation with weight 1.
std::vector< EntityId > ownedBy(const EntityId &owner) const
Returns entities owned by owner in deterministic ID order.
bool setOwner(const EntityId &entity, const EntityId &owner)
Sets an entity's owner; an empty owner removes ownership.
static EntityId integerId(std::int64_t id)
Converts a stable integer ID to its canonical graph key.
double addRelation(const EntityId &source, const EntityId &target, const std::string &type, double delta)
Adds delta to a directed typed relation and returns its new weight.
std::vector< EntityId > controlledBy(const EntityId &controller) const
Returns entities controlled by controller in deterministic ID order.
bool setRelation(const EntityId &source, const EntityId &target, const std::string &type, double value)
Sets a directed typed relation weight, creating the edge if needed.
bool unassign(const EntityId &source, const std::string &role, const EntityId &target)
Removes a role-based source-to-target assignment.
bool setController(const EntityId &entity, const EntityId &controller)
Sets an entity's controller; an empty controller removes control.
std::vector< EntityId > targetsOf(const EntityId &source, const std::string &role) const
Returns targets assigned from source with role in deterministic order.
bool removeEntity(const EntityId &entity)
Removes an entity and every incoming/outgoing graph reference to it.
std::vector< EntityId > assigneesOf(const EntityId &target, const std::string &role) const
Returns sources assigned to target with role in deterministic order.
EntityId ownerOf(const EntityId &entity) const
Returns an entity's owner, or an empty string when absent.
bool removeRelation(const EntityId &source, const EntityId &target, const std::string &type)
Removes an exact directed typed relation.
void clear()
Clears all graph state and pending events.
bool isAssigned(const EntityId &source, const std::string &role, const EntityId &target) const
Tests whether an exact assignment exists.
double relation(const EntityId &source, const EntityId &target, const std::string &type, double fallback=0.0) const
Gets an exact relation weight, or fallback when absent.
std::vector< EntityId > relationTargets(const EntityId &source, const std::string &type, double minimum=0.0) const
Returns outgoing relation targets filtered by type and minimum weight.
bool hasRelation(const EntityId &source, const EntityId &target, const std::string &type) const
Tests whether an exact directed typed relation exists.
std::vector< EntityId > relationSources(const EntityId &target, const std::string &type, double minimum=0.0) const
Returns incoming relation sources filtered by type and minimum weight.
std::string EntityId
Stable, game-defined identifier used by the social graph.
Definition SocialGraph.h:15