载入中...
搜索中...
未找到
Navigation.cpp
浏览该文件的文档.
1#include "npc_ai/Navigation.h"
2
3#include <algorithm>
4#include <cmath>
5
6namespace eve::npc_ai {
7namespace {
8bool finitePosition(const std::array<double, 3>& position) {
9 return std::all_of(position.begin(), position.end(), [](double value) { return std::isfinite(value); });
10}
11} // namespace
12
13NavigationTaskService::NavigationTaskService(std::unique_ptr<INavigationProvider> provider,
14 std::unique_ptr<INavigationRequestFactory> requestFactory)
15 : provider_(std::move(provider)), requestFactory_(std::move(requestFactory)) {}
16
18 std::unique_ptr<INavigationProvider> provider, std::unique_ptr<INavigationRequestFactory> requestFactory) {
19 if (!provider || !requestFactory)
21 DiagnosticCode::InvalidArgument, "navigation provider and request factory owners are required", {}, {},
22 "npc_ai.navigation"));
23 return Result<std::unique_ptr<NavigationTaskService>>::success(std::unique_ptr<NavigationTaskService>(
24 new NavigationTaskService(std::move(provider), std::move(requestFactory))));
25}
26
28 for (const auto& [task, ticket] : active_) {
29 (void)task;
30 provider_->abandon(ticket);
31 }
32}
33
34NavigationTaskService::TaskKey NavigationTaskService::key(const TaskContext& context, const TaskSpec& spec) {
35 return {context.agent, std::string(context.stateId), spec.id};
36}
37
39 std::string& inOutMemoryJson) {
40 const auto taskKey = key(context, spec);
41 if (active_.contains(taskKey))
43 "navigation task already owns an active ticket", {}, {},
44 "npc_ai.navigation"));
45 auto request = requestFactory_->create(context, spec);
46 if (!request.ok()) return Result<void>::failure(request.status());
47 if (request.value().agent != context.agent || !finitePosition(request.value().start) ||
48 !finitePosition(request.value().destination) || !std::isfinite(request.value().agentRadius) ||
49 !std::isfinite(request.value().acceptanceRadius) || request.value().agentRadius <= 0.0 ||
50 request.value().acceptanceRadius < 0.0 || request.value().requestedTick != context.simulationTick)
52 "navigation request factory returned an invalid request", {}, {},
53 "npc_ai.navigation"));
54 auto ticket = provider_->begin(request.value());
55 if (!ticket.ok()) return Result<void>::failure(ticket.status());
56 if (!ticket.value().isValid()) {
58 "navigation provider returned an invalid ticket", {}, {},
59 "npc_ai.navigation"));
60 }
61 active_.emplace(taskKey, ticket.value());
62 inOutMemoryJson = "{\"phase\":\"pending\"}";
64}
65
67 std::string& inOutMemoryJson) {
68 const auto found = active_.find(key(context, spec));
69 if (found == active_.end())
71 "navigation task has no active ticket", {}, {},
72 "npc_ai.navigation"));
73 auto progress = provider_->poll(found->second, context.simulationTick);
74 if (!progress.ok()) return Result<TaskStatus>::failure(progress.status());
75 if (!finitePosition(progress.value().desiredVelocity) || !std::isfinite(progress.value().remainingDistance) ||
76 progress.value().remainingDistance < 0.0)
78 "navigation provider returned invalid progress", {}, {},
79 "npc_ai.navigation"));
80 switch (progress.value().phase) {
82 inOutMemoryJson = "{\"phase\":\"pending\"}";
85 inOutMemoryJson = "{\"phase\":\"moving\"}";
88 active_.erase(found);
89 inOutMemoryJson = "{\"phase\":\"arrived\"}";
92 active_.erase(found);
93 inOutMemoryJson = "{\"phase\":\"unreachable\"}";
96 active_.erase(found);
97 inOutMemoryJson = "{\"phase\":\"cancelled\"}";
99 }
101 "navigation provider returned an unknown phase", {}, {},
102 "npc_ai.navigation"));
103}
104
106 std::string_view memoryJson) noexcept {
107 (void)reason;
108 (void)memoryJson;
109 const auto found = active_.find(key(context, spec));
110 if (found == active_.end()) return;
111 provider_->abandon(found->second);
112 active_.erase(found);
113}
114
115} // namespace eve::npc_ai
double value
const GltfImportRequest & request
std::uint32_t key
std::array< float, 3 > position
bool found
const VegetationPresetContext & context
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
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
ITaskService adapter for asynchronous move-to requests.
Definition Navigation.h:81
NavigationTaskService(const NavigationTaskService &)=delete
~NavigationTaskService() override
Navigation task service.
void stop(const TaskContext &context, const TaskSpec &spec, StopReason reason, std::string_view memoryJson) noexcept override
Stops .
Result< void > start(const TaskContext &context, const TaskSpec &spec, std::string &inOutMemoryJson) override
Starts .
static Result< std::unique_ptr< NavigationTaskService > > create(std::unique_ptr< INavigationProvider > provider, std::unique_ptr< INavigationRequestFactory > requestFactory)
Validates and transfers both required owners into a task service.
Result< TaskStatus > tick(const TaskContext &context, const TaskSpec &spec, std::string &inOutMemoryJson) override
Tick.
StopReason
StopReason public API.
Definition NpcAi.h:31
TaskContext public API.
Definition NpcAi.h:181
TaskSpec public API.
Definition NpcAi.h:63
std::string id
Definition NpcAi.h:64