载入中...
搜索中...
未找到
RTSTypes.cpp
浏览该文件的文档.
1#include "rts/RTSTypes.h"
2
4#include "common/Json.h"
8
9#include <algorithm>
10#include <cmath>
11#include <map>
12#include <utility>
13
14namespace eve::rts {
15namespace {
16
17bool finitePosition(WorldPosition position) { return std::isfinite(position.x) && std::isfinite(position.y); }
18
19bool handleEqual(const ecs::EntityHandle& left, const ecs::EntityHandle& right) {
20 return left.table == right.table && left.type == right.type && left.id == right.id &&
21 left.generation == right.generation;
22}
23
24std::optional<OrderKind> parseOrderKind(std::string_view kind) {
25 if (kind == "move") return OrderKind::Move;
26 if (kind == "attack") return OrderKind::Attack;
27 if (kind == "build") return OrderKind::Build;
28 if (kind == "gather") return OrderKind::Gather;
29 if (kind == "return_cargo") return OrderKind::ReturnCargo;
30 if (kind == "attack_move") return OrderKind::AttackMove;
31 if (kind == "stop") return OrderKind::Stop;
32 if (kind == "hold_position") return OrderKind::HoldPosition;
33 if (kind == "patrol") return OrderKind::Patrol;
34 if (kind == "repair") return OrderKind::Repair;
35 if (kind == "garrison") return OrderKind::Garrison;
36 if (kind == "board_transport") return OrderKind::BoardTransport;
37 if (kind == "capture") return OrderKind::Capture;
38 if (kind == "attack_ground") return OrderKind::AttackGround;
39 if (kind == "resupply") return OrderKind::Resupply;
40 if (kind == "escort") return OrderKind::Escort;
41 if (kind == "suppress_area") return OrderKind::SuppressArea;
42 if (kind == "supply_relay") return OrderKind::SupplyRelay;
43 return std::nullopt;
44}
45
46Result<OrderRecord> projectOrder(const orders::Order& order, const CommandSpec* extended = nullptr) {
47 const auto kind = parseOrderKind(order.kind);
48 if (!kind) {
50 DiagnosticCode::InvariantViolation, "generic order contains an unknown RTS kind", "order.kind"));
51 }
52
53 const std::string json = order.payload.toJson();
54 std::string errorText;
55 auto document = json::Document::parse(json, &errorText);
56 if (!document.valid() || !document.root().isObject()) {
58 DiagnosticCode::ParseError, "generic order payload is not a JSON object", "order.payload"));
59 }
60
61 const auto root = document.root();
62 OrderRecord result;
63 result.id = order.id;
64 result.kind = *kind;
65 result.target.x = root.get("x").asFloat(0.0f);
66 result.target.y = root.get("y").asFloat(0.0f);
67 result.definitionId = root.get("definition").asString();
68 result.formationSlot = root.get("formationSlot").asInt(-1);
69 result.secondaryTarget.x = root.get("secondaryX").asFloat(0.0f);
70 result.secondaryTarget.y = root.get("secondaryY").asFloat(0.0f);
71 result.radius = root.get("radius").asFloat(0.0f);
72 result.append = root.get("append").asBool(false);
73 if (extended != nullptr) {
74 result.targetEntity = extended->targetEntity;
75 }
76 if (!finitePosition(result.target)) {
78 DiagnosticCode::InvariantViolation, "generic order payload contains a non-finite target", "order.payload"));
79 }
80 return Result<OrderRecord>::success(std::move(result));
81}
82
83void touchUnitComponents(Unit& unit) {
84 (void)unit.identity();
85 (void)unit.definition();
86 (void)unit.attributes();
87 (void)unit.tags();
88 (void)unit.effects();
89 (void)unit.orders();
90 (void)unit.sensing();
91 (void)unit.steering();
92 (void)unit.crowd();
93 (void)unit.weapon();
94 (void)unit.action();
95 (void)unit.settlement();
96 (void)unit.faction();
97 (void)unit.motion();
98 (void)unit.navigation();
99 (void)unit.vision();
100 (void)unit.worker();
101 (void)unit.combat();
102 (void)unit.durability();
103 (void)unit.capture();
104 (void)unit.containment();
105 (void)unit.supply();
106 (void)unit.morale();
107 (void)unit.artillery();
108 (void)unit.tactics();
109 (void)unit.technology();
110}
111
112void touchBuildingComponents(Building& building) {
113 (void)building.identity();
114 (void)building.definition();
115 (void)building.placement();
116 (void)building.production();
117 (void)building.economy();
118 (void)building.orders();
119 (void)building.tags();
120 (void)building.effects();
121 (void)building.settlement();
122 (void)building.faction();
123 (void)building.construction();
124 (void)building.integrity();
125 (void)building.capture();
126 (void)building.dropoff();
127 (void)building.rally();
128 (void)building.weapon();
129 (void)building.combat();
130 (void)building.garrison();
131 (void)building.supply();
132 (void)building.vision();
133 (void)building.technology();
134}
135
136void touchResourceNodeComponents(ResourceNode& node) {
137 (void)node.identity();
138 (void)node.position();
139 (void)node.stock();
140 (void)node.harvest();
141}
142
143void touchPlayerComponents(Player& player) {
144 (void)player.identity();
145 (void)player.authority();
146 (void)player.economy();
147 (void)player.social();
148 (void)player.selection();
149 (void)player.eventStream();
150}
151
152void touchFactionComponents(Faction& faction) {
153 (void)faction.identity();
154 (void)faction.authority();
155 (void)faction.economy();
156 (void)faction.social();
157 (void)faction.members();
158 (void)faction.eventStream();
159 (void)faction.strategy();
160 (void)faction.workforce();
161 (void)faction.productionPolicy();
162 (void)faction.intel();
163 (void)faction.technology();
164}
165
166} // namespace
167
168const char* combatStanceName(CombatStance stance) noexcept {
169 switch (stance) {
170 case CombatStance::Passive: return "passive";
171 case CombatStance::Defensive: return "defensive";
172 case CombatStance::Aggressive: return "aggressive";
173 }
174 return "defensive";
175}
176
177const char* orderKindName(OrderKind kind) noexcept {
178 switch (kind) {
179 case OrderKind::Move: return "move";
180 case OrderKind::Attack: return "attack";
181 case OrderKind::Build: return "build";
182 case OrderKind::Gather: return "gather";
183 case OrderKind::ReturnCargo: return "return_cargo";
184 case OrderKind::AttackMove: return "attack_move";
185 case OrderKind::Stop: return "stop";
186 case OrderKind::HoldPosition: return "hold_position";
187 case OrderKind::Patrol: return "patrol";
188 case OrderKind::Repair: return "repair";
189 case OrderKind::Garrison: return "garrison";
190 case OrderKind::BoardTransport: return "board_transport";
191 case OrderKind::Capture: return "capture";
192 case OrderKind::AttackGround: return "attack_ground";
193 case OrderKind::Resupply: return "resupply";
194 case OrderKind::Escort: return "escort";
195 case OrderKind::SuppressArea: return "suppress_area";
196 case OrderKind::SupplyRelay: return "supply_relay";
197 }
198 return "unknown";
199}
200
202 if (!finitePosition(target) || !finitePosition(secondaryTarget)) {
203 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS command target must contain finite coordinates", "target"));
204 }
205 if (!std::isfinite(timeoutSeconds) || timeoutSeconds < 0.0) {
206 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS command timeout must be finite and non-negative", "timeoutSeconds"));
207 }
208 if (!std::isfinite(radius) || radius < 0.0f)
209 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS command radius must be finite and non-negative", "radius"));
210 switch (kind) {
211 case OrderKind::Move:
213 case OrderKind::Build:
217 case OrderKind::Stop:
229 }
230 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS command kind is invalid", "kind"));
231}
232
233Result<void> TagSet::add(std::string_view tag) {
234 if (tag.empty()) return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS tag must not be empty", "tag"));
235 auto it = std::lower_bound(values_.begin(), values_.end(), tag,
236 [](const std::string& value, std::string_view key) { return value < key; });
237 if (it != values_.end() && *it == tag) return Result<void>::success(Status::success(StatusCode::NoOp));
238 values_.insert(it, std::string(tag));
240}
241
242Result<void> TagSet::remove(std::string_view tag) {
243 if (tag.empty()) return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS tag must not be empty", "tag"));
244 auto it = std::lower_bound(values_.begin(), values_.end(), tag,
245 [](const std::string& value, std::string_view key) { return value < key; });
246 if (it == values_.end() || *it != tag) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "RTS tag is not present", "tag"));
247 values_.erase(it);
249}
250
251bool TagSet::contains(std::string_view tag) const noexcept {
252 const auto it = std::lower_bound(values_.begin(), values_.end(), tag,
253 [](const std::string& value, std::string_view key) { return value < key; });
254 return it != values_.end() && *it == tag;
255}
256
260
264 : impl_(other.impl_ ? std::make_unique<Impl>(*other.impl_) : nullptr) {}
266 if (this == &other) return *this;
267 impl_ = other.impl_ ? std::make_unique<Impl>(*other.impl_) : nullptr;
268 return *this;
269}
272
273Result<void> AttributeComponent::setBase(std::string_view attribute, double value) {
274 if (attribute.empty() || !std::isfinite(value)) {
275 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS attribute base requires a non-empty finite value", "attribute"));
276 }
277 if (!impl_) impl_ = std::make_unique<Impl>();
278 return impl_->values.setBase(attribute, value);
279}
280
281Result<void> AttributeComponent::modifyBase(std::string_view attribute, double delta) {
282 if (attribute.empty() || !std::isfinite(delta)) {
283 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS attribute delta requires a non-empty finite value", "attribute"));
284 }
285 if (!impl_) impl_ = std::make_unique<Impl>();
286 return impl_->values.modifyBase(attribute, delta);
287}
288
289bool AttributeComponent::has(std::string_view attribute) const {
290 return impl_ && impl_->values.has(std::string(attribute));
291}
292
293Result<double> AttributeComponent::getFinal(std::string_view attribute, double fallback) const {
294 if (attribute.empty() || !std::isfinite(fallback)) {
296 "RTS attribute query requires a non-empty finite key/fallback",
297 "attribute"));
298 }
299 if (!impl_) return Result<double>::success(fallback, Status::success(StatusCode::NoOp));
300 return impl_->values.getFinal(attribute, fallback);
301}
302
303std::size_t AttributeComponent::modifierCount() const noexcept {
304 return impl_ ? static_cast<std::size_t>(impl_->values.modifierCount()) : 0u;
305}
306
308 return impl_ ? impl_->values.modifierAt(index) : nullptr;
309}
310
312 if (!impl_) impl_ = std::make_unique<Impl>();
313 return impl_->values.bindOwner(owner);
314}
315
316bool AttributeComponent::initialized() const noexcept { return impl_ != nullptr && impl_->values.initialized(); }
317
318Result<void> AttributeComponent::initialize(std::span<const eve::attributes::AttributeSnapshotBase> values) {
319 if (!impl_) impl_ = std::make_unique<Impl>();
320 return impl_->values.initialize(values);
321}
322
323bool AttributeComponent::isStale() const noexcept { return impl_ != nullptr && impl_->values.isStale(); }
324
326 if (!impl_) impl_ = std::make_unique<Impl>();
327 return impl_->values.addModifier(std::move(modifier));
328}
329
331 std::span<const std::string_view> attributes) const {
332 if (!impl_)
334 DiagnosticCode::InvariantViolation, "RTS attribute component is not initialized", "attributes"));
335 return impl_->values.snapshot(attributes);
336}
337
339 Revision expectedRevision) {
340 if (!impl_) impl_ = std::make_unique<Impl>();
341 return impl_->values.restore(snapshot, expectedRevision);
342}
343
346 std::map<std::string, CommandSpec> extended;
347};
348
349OrderComponent::OrderComponent() : impl_(std::make_unique<Impl>()) {}
352 : impl_(other.impl_ ? std::make_unique<Impl>(*other.impl_) : nullptr) {}
354 if (this == &other) return *this;
355 impl_ = other.impl_ ? std::make_unique<Impl>(*other.impl_) : nullptr;
356 ++membershipEpoch_;
357 return *this;
358}
360 : membershipEpoch_(other.membershipEpoch_), impl_(std::move(other.impl_)) {
361 ++other.membershipEpoch_;
362}
364 if (this != &other) {
365 impl_ = std::move(other.impl_);
366 ++membershipEpoch_;
367 ++other.membershipEpoch_;
368 }
369 return *this;
370}
371
372Result<std::string> OrderComponent::enqueue(const CommandSpec& command, int formationSlot) {
373 auto valid = command.validate();
374 if (!valid) return Result<std::string>::failure(valid.status());
375 if (!impl_) impl_ = std::make_unique<Impl>();
376 auto queued = impl_->queue.append(orderKindName(command.kind), command.priority, command.timeoutSeconds);
377 if (!queued) return Result<std::string>::failure(queued.status());
378 const std::string id = std::move(queued).takeValue();
379 auto order = impl_->queue.find(id);
380 if (!order)
382 DiagnosticCode::InvariantViolation, "generic order queue lost its newly appended command", "order"));
383 order->get().payload.setNumber("x", command.target.x);
384 order->get().payload.setNumber("y", command.target.y);
385 order->get().payload.setString("definition", command.definitionId);
386 order->get().payload.setNumber("formationSlot", static_cast<double>(formationSlot));
387 order->get().payload.setNumber("secondaryX", command.secondaryTarget.x);
388 order->get().payload.setNumber("secondaryY", command.secondaryTarget.y);
389 order->get().payload.setNumber("radius", command.radius);
390 order->get().payload.setBool("append", command.append);
391 impl_->extended[id] = command;
393}
394
395Result<std::string> OrderComponent::replace(const CommandSpec& command, int formationSlot) {
396 auto valid = command.validate();
397 if (!valid) return Result<std::string>::failure(valid.status());
398 if (!impl_) impl_ = std::make_unique<Impl>();
399 auto queued = impl_->queue.replace(orderKindName(command.kind), command.priority, command.timeoutSeconds);
400 if (!queued) return Result<std::string>::failure(queued.status());
401 const std::string id = std::move(queued).takeValue();
402 auto order = impl_->queue.find(id);
403 if (!order)
405 DiagnosticCode::InvariantViolation, "generic order queue lost its replacement command", "order"));
406 order->get().payload.setNumber("x", command.target.x);
407 order->get().payload.setNumber("y", command.target.y);
408 order->get().payload.setString("definition", command.definitionId);
409 order->get().payload.setNumber("formationSlot", static_cast<double>(formationSlot));
410 order->get().payload.setNumber("secondaryX", command.secondaryTarget.x);
411 order->get().payload.setNumber("secondaryY", command.secondaryTarget.y);
412 order->get().payload.setNumber("radius", command.radius);
413 order->get().payload.setBool("append", command.append);
414 impl_->extended.clear();
415 impl_->extended[id] = command;
417}
418
420 if (!impl_ || !impl_->queue.current())
422 Diagnostic::error(DiagnosticCode::NotFound, "RTS order queue is idle", "order"));
423 const auto& order = impl_->queue.current()->get();
424 const auto found = impl_->extended.find(order.id);
425 return projectOrder(order, found == impl_->extended.end() ? nullptr : &found->second);
426}
427
428Result<void> OrderComponent::complete(std::string_view orderId) {
429 if (orderId.empty()) return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS order id must not be empty", "orderId"));
430 if (!impl_ || !impl_->queue.find(std::string(orderId)))
431 return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "RTS order id is not present", "orderId"));
432 if (!impl_->queue.complete(std::string(orderId)).ok())
433 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Conflict, "RTS order is not active or is already terminal", "orderId"));
434 impl_->extended.erase(std::string(orderId));
436}
437
438Result<void> OrderComponent::fail(std::string_view orderId, std::string_view reason) {
439 if (orderId.empty() || reason.empty())
440 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS order failure requires an id and reason", "order"));
441 if (!impl_ || !impl_->queue.find(std::string(orderId)))
442 return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "RTS order id is not present", "orderId"));
443 if (!impl_->queue.fail(std::string(orderId), std::string(reason)).ok())
444 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Conflict, "RTS order is not active", "orderId"));
445 impl_->extended.erase(std::string(orderId));
447}
448
449Result<void> OrderComponent::cancel(std::string_view orderId, std::string_view reason) {
450 if (orderId.empty() || reason.empty())
451 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "RTS order cancellation requires an id and reason", "order"));
452 if (!impl_ || !impl_->queue.find(std::string(orderId)))
453 return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "RTS order id is not present", "orderId"));
454 if (!impl_->queue.cancel(std::string(orderId), std::string(reason)).ok())
455 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Conflict, "RTS order is already terminal", "orderId"));
456 impl_->extended.erase(std::string(orderId));
458}
459
460bool OrderComponent::empty() const noexcept { return !impl_ || !impl_->queue.current(); }
461
462void OrderComponent::clear() noexcept {
463 ++membershipEpoch_;
464 if (!impl_) return;
465 impl_->queue.clear();
466 impl_->extended.clear();
467}
468
469std::size_t OrderComponent::orderCount() const noexcept {
470 return impl_ ? static_cast<std::size_t>(impl_->queue.orderCount()) : 0u;
471}
472
474 if (!impl_)
476 Diagnostic::error(DiagnosticCode::Failed, "RTS order component is unavailable", "orders"));
477 return impl_->queue.snapshot();
478}
479
480Result<void> OrderComponent::restore(std::string_view json) {
481 if (!impl_) impl_ = std::make_unique<Impl>();
482 orders::CommandQueue candidate;
483 auto restored = candidate.restore(json);
484 if (!restored) return restored;
485 impl_->queue = std::move(candidate);
486 impl_->extended.clear();
487 ++membershipEpoch_;
489}
490
492 if (!impl_)
494 Diagnostic::error(DiagnosticCode::Failed, "RTS order component is unavailable", "orders"));
495 auto json = impl_->queue.snapshot();
496 if (!json) return Result<Snapshot>::failure(json.status());
497 return Result<Snapshot>::success({std::move(json).takeValue(), impl_->extended},
499}
500
503 auto restored = queue.restore(snapshotValue.queueJson);
504 if (!restored) return restored;
505 for (const auto& [id, command] : snapshotValue.extended) {
506 auto valid = command.validate();
507 if (!valid) return valid;
508 if (!queue.find(id))
509 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Conflict, "RTS order extension references an absent canonical queue record", "orders.extended"));
510 }
511 auto candidate = std::make_unique<Impl>();
512 candidate->queue = std::move(queue);
513 candidate->extended = snapshotValue.extended;
514 impl_ = std::move(candidate);
515 ++membershipEpoch_;
517}
518
519orders::CommandQueue* OrderComponent::queueForComposition() noexcept {
520 if (!impl_) impl_ = std::make_unique<Impl>();
521 return &impl_->queue;
522}
523
526
527 Impl() = default;
528 Impl(const Impl& other) {
529 auto snapshot = other.queue.snapshot();
530 if (snapshot) (void)queue.restore(snapshot.value());
531 }
532 Impl& operator=(const Impl& other) {
533 if (this == &other) return *this;
534 auto snapshot = other.queue.snapshot();
535 if (snapshot) (void)queue.restore(snapshot.value());
536 return *this;
537 }
538};
539
543 : impl_(other.impl_ ? std::make_unique<Impl>(*other.impl_) : nullptr) {}
545 if (this == &other) return *this;
546 impl_ = other.impl_ ? std::make_unique<Impl>(*other.impl_) : nullptr;
547 return *this;
548}
551
552Result<std::string> ProductionComponent::enqueue(std::string_view owner, std::string_view kind,
553 std::string_view product, Duration duration, int priority) {
554 if (owner.empty() || kind.empty() || product.empty() || duration.nanoseconds() <= 0)
557 "RTS production requires non-empty ids and a positive duration", "production"));
558 if (!impl_) impl_ = std::make_unique<Impl>();
559 return impl_->queue.enqueue(owner, kind, product, eve::Value(eve::Value::Object{}), duration.seconds(), priority);
560}
561
563 if (!impl_) impl_ = std::make_unique<Impl>();
564 return impl_->queue.enqueue(std::move(request));
565}
566
568 if (!impl_) impl_ = std::make_unique<Impl>();
569 return impl_->queue.advance(step);
570}
571
572std::size_t ProductionComponent::taskCount() const noexcept {
573 return impl_ ? static_cast<std::size_t>(impl_->queue.taskCount()) : 0u;
574}
575
579
583
585 if (!impl_)
587 Diagnostic::error(DiagnosticCode::NotFound, "RTS production task was not found", "taskId"));
588 return impl_->queue.pause(taskId);
589}
590
592 if (!impl_)
594 Diagnostic::error(DiagnosticCode::NotFound, "RTS production task was not found", "taskId"));
595 return impl_->queue.resume(taskId);
596}
597
598Result<void> ProductionComponent::cancel(std::string_view taskId, std::string_view reason) {
599 if (!impl_)
601 Diagnostic::error(DiagnosticCode::NotFound, "RTS production task was not found", "taskId"));
602 return impl_->queue.cancel(taskId, reason);
603}
604
605std::vector<production::ProductionTask> ProductionComponent::readyToSettle(std::string_view kind) const {
606 std::vector<production::ProductionTask> result;
607 if (!impl_ || kind.empty()) return result;
608 for (int index = 0; index < impl_->queue.taskCount(); ++index) {
609 const auto task = impl_->queue.taskAt(index);
610 if (task && task->get().kind == kind && task->get().state == production::TaskState::ReadyToSettle)
611 result.push_back(task->get());
612 }
613 return result;
614}
615
617 if (!impl_)
619 Diagnostic::error(DiagnosticCode::NotFound, "RTS production task was not found", "taskId"));
620 return impl_->queue.settle(taskId, std::move(receipt));
621}
622
624 if (!impl_)
626 Diagnostic::error(DiagnosticCode::Failed, "RTS production component is unavailable", "production"));
627 return impl_->queue.snapshot();
628}
629
631 if (!impl_) impl_ = std::make_unique<Impl>();
632 production::WorkQueue candidate;
633 auto restored = candidate.restore(json);
634 if (!restored) return restored;
635 impl_->queue = std::move(candidate);
637}
638
639production::WorkQueue* ProductionComponent::queueForComposition() noexcept {
640 if (!impl_) impl_ = std::make_unique<Impl>();
641 return &impl_->queue;
642}
643
645 Unit* unit = Unit::create();
646 unit->identity()->self = ecs::handle_of(unit);
647 unit->identity()->subject = subject;
648 unit->definition()->id = std::move(definition);
649 unit->durability()->state.subject = subject;
650 unit->durability()->state.health = 1.0;
651 unit->durability()->state.maxHealth = 1.0;
652 touchUnitComponents(*unit);
653 return unit;
654}
655
657 Building* building = Building::create();
658 building->identity()->self = ecs::handle_of(building);
659 building->identity()->subject = subject;
660 building->definition()->id = std::move(definition);
661 building->integrity()->state.subject = subject;
662 building->integrity()->state.health = 1.0;
663 building->integrity()->state.maxHealth = 1.0;
664 touchBuildingComponents(*building);
665 return building;
666}
667
669 ResourceNode* node = ResourceNode::create();
670 node->identity()->self = ecs::handle_of(node);
671 node->identity()->subject = subject;
672 touchResourceNodeComponents(*node);
673 return node;
674}
675
677 Player* player = Player::create();
678 player->identity()->self = ecs::handle_of(player);
679 player->identity()->subject = subject;
680 touchPlayerComponents(*player);
681 return player;
682}
683
685 Faction* faction = Faction::create();
686 faction->identity()->self = ecs::handle_of(faction);
687 faction->identity()->subject = subject;
688 touchFactionComponents(*faction);
689 return faction;
690}
691
693 Match* match = Match::create();
694 if (match == nullptr) return nullptr;
695 match->identity()->self = ecs::handle_of(match);
696 match->identity()->subject = subject;
697 (void)match->rules();
698 (void)match->participants();
699 (void)match->state();
700 (void)match->events();
701 return match;
702}
703
704} // namespace eve::rts
double value
float duration
int root
Definition AnimSmr.cpp:119
int subject
Definition AnimSmr.cpp:163
int priority
std::map< std::string, Var > values
Owning effect storage and lifecycle-only executor.
const GltfImportRequest & request
std::uint32_t key
float u
Definition Grass.cpp:233
HexVec3 left
HexVec3 right
TokenKind kind
std::array< float, 3 > position
bool valid
std::vector< std::int32_t > order
const std::string * tag
size_t queued
Definition OnnxGpgpu.cpp:60
std::string id
Definition PlayHost.cpp:108
std::string taskId
RTS domain roots and composition-only components.
const RoadNode * node
bool found
TacticalUnit * unit
float step
Definition TreeMesh.cpp:314
uint32_t index
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Signed, fixed-resolution simulation duration in nanoseconds.
Definition Time.h:43
Human-readable, scoped identifier in the form namespace:name.
Definition Identity.h:411
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
Strong, domain-neutral reference to a runtime subject.
Definition SubjectRef.h:26
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
std::map< std::string, Value > Object
Definition Value.h:34
Canonical selected-attribute storage with owner and revision checks.
static Document parse(const std::string &text, std::string *error=nullptr)
Parse.
Definition Json.cpp:581
Generic priority order queue with no gameplay or entity semantics.
eve::Result< void > restore(std::string_view json)
Restores a command queue transactionally from a JSON snapshot.
eve::OptionalRef< Order > find(const std::string &id)
Returns an order by stable id, including terminal history.
Generic multi-owner, multi-slot continuous-progress work queue.
Definition Production.h:200
eve::Result< std::string > snapshot() const
Serializes the complete queue as deterministic JSON.
eve::Result< void > restore(std::string_view json)
Transactionally restores a snapshot; failure preserves current state.
Canonical attributes component adapter, backed by attributes::AttributeSet.
Definition RTSTypes.h:323
AttributeComponent()
Attribute component.
Definition RTSTypes.cpp:261
std::size_t modifierCount() const noexcept
Return the number of canonical modifiers.
Definition RTSTypes.cpp:303
Result< void > modifyBase(std::string_view attribute, double delta)
Add to one authoritative base value.
Definition RTSTypes.cpp:281
AttributeComponent & operator=(const AttributeComponent &other)
Operator =.
Definition RTSTypes.cpp:265
Result< void > bindOwner(ecs::EntityHandle owner)
Bind the canonical attribute state to an ECS owner generation.
Definition RTSTypes.cpp:311
Result< eve::attributes::ModifierId > addModifier(eve::attributes::AttributeModifier modifier)
Add a modifier with the common source/priority/sequence contract.
Definition RTSTypes.cpp:325
bool has(std::string_view attribute) const
Return whether an attribute exists.
Definition RTSTypes.cpp:289
Result< eve::attributes::AttributeProjectionSnapshot > snapshot(std::span< const std::string_view > attributes) const
Capture selected values with owner and revision metadata.
Definition RTSTypes.cpp:330
Result< void > setBase(std::string_view attribute, double value)
Set one authoritative base value.
Definition RTSTypes.cpp:273
bool isStale() const noexcept
Return whether the canonical attribute owner is stale.
Definition RTSTypes.cpp:323
Result< void > initialize(std::span< const eve::attributes::AttributeSnapshotBase > values)
Seed unit stat bases once without replacing existing values.
Definition RTSTypes.cpp:318
bool initialized() const noexcept
Return whether initial unit stat bases have been installed.
Definition RTSTypes.cpp:316
~AttributeComponent()
Attribute component.
const eve::attributes::AttributeModifier * modifierAt(int index) const noexcept
Return a canonical modifier in deterministic sequence order.
Definition RTSTypes.cpp:307
Result< double > getFinal(std::string_view attribute, double fallback=0.0) const
Read the deterministic final value or a caller-supplied default.
Definition RTSTypes.cpp:293
Result< void > restore(const eve::attributes::AttributeProjectionSnapshot &snapshot, Revision expectedRevision)
Restore selected values after generation and revision checks.
Definition RTSTypes.cpp:338
RTS building domain root with placement and production composition.
Definition RTSTypes.h:840
static Building * createBuilding(SubjectRef subject={}, LogicalId definition={})
Create a building and initialize its self handle and identity.
Definition RTSTypes.cpp:656
Faction domain root; membership is a set of typed runtime handles.
Definition RTSTypes.h:1178
static Faction * createFaction(SubjectRef subject={})
Create a faction and initialize its self handle and identity.
Definition RTSTypes.cpp:684
Independent match composition root; factions may participate in different matches.
Definition RTSTypes.h:1295
static Match * createMatch(SubjectRef subject={})
Create a match and initialize every composition component. @ownership The active ECS table owns the e...
Definition RTSTypes.cpp:692
Generic orders component adapter; the queue remains the sole order owner.
Definition RTSTypes.h:385
Result< std::string > snapshot() const
Serialize the canonical generic queue for persistence/replay.
Definition RTSTypes.cpp:473
Result< Snapshot > snapshotState() const
Capture the generic queue and every RTS-specific payload atomically.
Definition RTSTypes.cpp:491
void clear() noexcept
Remove active, queued, and retained order history.
Definition RTSTypes.cpp:462
Result< void > complete(std::string_view orderId)
Complete the active order by its stable queue id.
Definition RTSTypes.cpp:428
Result< void > restoreState(const Snapshot &snapshot)
Transactionally restore a complete RTS order projection.
Definition RTSTypes.cpp:501
Result< OrderRecord > current() const
Project the active order or return NotFound when idle.
Definition RTSTypes.cpp:419
Result< void > restore(std::string_view json)
Transactionally restore the canonical generic queue.
Definition RTSTypes.cpp:480
std::size_t orderCount() const noexcept
Return the number of retained order records.
Definition RTSTypes.cpp:469
Result< std::string > replace(const CommandSpec &command, int formationSlot=-1)
Replace unfinished commands with one new command.
Definition RTSTypes.cpp:395
Result< void > cancel(std::string_view orderId, std::string_view reason)
Cancel an active or queued order by its stable queue id.
Definition RTSTypes.cpp:449
OrderComponent & operator=(const OrderComponent &other)
Definition RTSTypes.cpp:353
bool empty() const noexcept
Return whether no order is currently retained.
Definition RTSTypes.cpp:460
Result< void > fail(std::string_view orderId, std::string_view reason)
Fail the active order by its stable queue id.
Definition RTSTypes.cpp:438
Result< std::string > enqueue(const CommandSpec &command, int formationSlot=-1)
Append a Move/Attack/Build/Gather command.
Definition RTSTypes.cpp:372
Player domain root; selection is RTS-local, authority/economy/social are links.
Definition RTSTypes.h:1119
static Player * createPlayer(SubjectRef subject={})
Create a player and initialize its self handle and identity.
Definition RTSTypes.cpp:676
Production adapter whose queue owns all task state.
Definition RTSTypes.h:438
Result< void > cancel(std::string_view taskId, std::string_view reason="cancelled")
Cancel a non-terminal task through the canonical queue.
Definition RTSTypes.cpp:598
Result< void > resume(std::string_view taskId)
Resume a paused task through the canonical queue.
Definition RTSTypes.cpp:591
Result< void > pause(std::string_view taskId)
Pause a queued or running task through the canonical queue.
Definition RTSTypes.cpp:584
~ProductionComponent()
Production component.
Result< void > restore(std::string_view json)
Transactionally restore the canonical production queue.
Definition RTSTypes.cpp:630
Result< void > settle(std::string_view taskId, production::ProductionSettlementReceipt receipt)
Commit one domain settlement with an idempotency receipt.
Definition RTSTypes.cpp:616
Result< std::string > enqueue(std::string_view owner, std::string_view kind, std::string_view product, Duration duration, int priority=0)
Enqueue a production task with an injected simulation duration.
Definition RTSTypes.cpp:552
std::size_t taskCount() const noexcept
Return the number of retained tasks.
Definition RTSTypes.cpp:572
ProductionComponent & operator=(const ProductionComponent &other)
Operator =.
Definition RTSTypes.cpp:544
OptionalRef< const production::ProductionTask > taskAt(int index)
Borrow a retained canonical task by enqueue index.
Definition RTSTypes.cpp:576
ProductionComponent()
Production component.
Definition RTSTypes.cpp:540
Result< void > advance(const SimulationStep &step)
Advance the queue using a caller-owned deterministic step.
Definition RTSTypes.cpp:567
std::vector< production::ProductionTask > readyToSettle(std::string_view kind) const
Copy work-complete tasks of one kind that await domain settlement.
Definition RTSTypes.cpp:605
Result< std::string > snapshot() const
Serialize the canonical production queue for persistence/replay.
Definition RTSTypes.cpp:623
OptionalRef< const production::ProductionTask > find(std::string_view taskId)
Borrow a retained canonical task by stable task id.
Definition RTSTypes.cpp:580
Harvestable RTS resource node; deposited balances are owned by an external resource account.
Definition RTSTypes.h:1071
static ResourceNode * createResourceNode(SubjectRef subject={})
Create a resource node and initialize all composition components. @ownership The active ECS table own...
Definition RTSTypes.cpp:668
bool contains(std::string_view tag) const noexcept
Test exact tag membership.
Definition RTSTypes.cpp:251
Result< void > add(std::string_view tag)
Add a tag in deterministic lexical order.
Definition RTSTypes.cpp:233
Result< void > remove(std::string_view tag)
Remove a tag, returning NotFound when it is absent.
Definition RTSTypes.cpp:242
RTS unit domain root.
Definition RTSTypes.h:495
static Unit * createUnit(SubjectRef subject={}, LogicalId definition={})
Create a unit and initialize its self handle and identity.
Definition RTSTypes.cpp:644
const char * combatStanceName(CombatStance stance) noexcept
Return the stable lower-case spelling of a combat stance. @ownership Returns a borrowed pointer to im...
Definition RTSTypes.cpp:168
OrderKind
Commands shared by movement, combat, construction and gathering.
Definition RTSTypes.h:64
CombatStance
Automatic target-acquisition policy for an RTS unit.
Definition RTSTypes.h:54
const char * orderKindName(OrderKind kind) noexcept
Return the stable lower-case spelling of an RTS order kind.
Definition RTSTypes.cpp:177
std::optional< std::reference_wrapper< T > > OptionalRef
Optional borrowed reference; it does not extend T's lifetime.
Definition BorrowedRef.h:24
One deterministic fixed-step emitted by SimulationClock.
Definition Time.h:158
One canonical runtime modifier applied to one named attribute.
Transaction-safe snapshot of selected attributes and their modifiers.
Validated input used to create a domain-neutral production task.
Definition Production.h:137
Owning proof that a domain consumer published one task exactly once.
Definition Production.h:46
attributes::AttributeProjection values
Definition RTSTypes.cpp:258
One domain-neutral command submitted to a unit's generic order queue.
Definition RTSTypes.h:101
std::string definitionId
Definition RTSTypes.h:104
Result< void > validate() const
Validate coordinates and command metadata without mutating state.
Definition RTSTypes.cpp:201
WorldPosition target
Definition RTSTypes.h:103
WorldPosition secondaryTarget
Definition RTSTypes.h:108
orders::CommandQueue queue
Definition RTSTypes.cpp:345
std::map< std::string, CommandSpec > extended
Definition RTSTypes.cpp:346
Complete RTS order projection snapshot; entity handles must be rebound by the owning domain.
Definition RTSTypes.h:388
std::map< std::string, CommandSpec > extended
Definition RTSTypes.h:390
Impl & operator=(const Impl &other)
Definition RTSTypes.cpp:532