载入中...
搜索中...
未找到
ArtifactProvider.cpp
浏览该文件的文档.
2
3#include "common/Capability.h"
4
5#include <algorithm>
6#include <charconv>
7#include <limits>
8#include <memory>
9#include <type_traits>
10#include <unordered_set>
11#include <utility>
12
13namespace eve::map {
14
15const eve::Value* member(const eve::Value::Object& object, const char* name) noexcept {
16 const auto found = object.find(name);
17 return found == object.end() ? nullptr : &found->second;
18}
19
20bool readString(const eve::Value::Object& object, const char* name, std::string& output) {
21 const auto* value = member(object, name);
22 const auto* text = value ? value->getIf<std::string>() : nullptr;
23 if (!text || text->empty()) return false;
24 output = *text;
25 return true;
26}
27
28bool readU64(const eve::Value::Object& object, const char* name, std::uint64_t& output) {
29 std::string text;
30 if (!readString(object, name, text)) return false;
31 const auto [end, error] = std::from_chars(text.data(), text.data() + text.size(), output);
32 return error == std::errc{} && end == text.data() + text.size();
33}
34
35bool readI64(const eve::Value::Object& object, const char* name, std::int64_t& output) {
36 const auto* value = member(object, name);
37 if (!value) return false;
38 if (const auto* integer = value->getIf<std::int64_t>()) {
39 output = *integer;
40 return true;
41 }
42 return false;
43}
44
45bool hasSupportedVersion(const eve::Value::Object& object) noexcept {
46 const auto* encoded = member(object, "version");
47 const auto* version = encoded ? encoded->getIf<std::int64_t>() : nullptr;
48 return version && *version == 1;
49}
50
52public:
54 : owner_(&owner), record_(std::move(record)) {}
55 void commit() noexcept override {
56 if (!owner_) return;
57 owner_->commit(std::move(record_));
58 owner_ = nullptr;
59 }
60 void rollback() noexcept override {
61 owner_ = nullptr;
62 record_ = {};
63 }
64
65private:
66 MapArtifactProvider* owner_ = nullptr;
67 MapArtifactRecord record_;
68};
70 const eve::artifact::PublicationView& publication) {
71 if (failPrepare_)
73 eve::Diagnostic::error(eve::DiagnosticCode::Failed, "map artifact prepare failure was injected"));
74 if (publication.id.isNil() || publication.buildKey.empty())
76 eve::DiagnosticCode::InvalidArgument, "map publication requires identity and build key"));
77 if (find(publication.id) != nullptr)
79 eve::Diagnostic::error(eve::DiagnosticCode::Conflict, "map artifact identity is already published"));
80
81 const eve::artifact::PartView* topology = nullptr;
82 for (const auto& part : publication.parts) {
83 if (part.kind == eve::artifact::PartKind::Grid && (part.role == "topology" || topology == nullptr))
84 topology = &part;
85 }
86 if (!topology || topology->width <= 0 || topology->height <= 0 ||
87 topology->cells.size() !=
88 static_cast<std::size_t>(topology->width) * static_cast<std::size_t>(topology->height))
89 return eve::Result<std::unique_ptr<eve::artifact::PreparedPublication>>::failure(eve::Diagnostic::error(
90 eve::DiagnosticCode::PreconditionViolation, "map publication requires a complete grid topology"));
91 if (nextIndex_ == MapArtifactHandle::invalidIndex)
93 eve::Diagnostic::error(eve::DiagnosticCode::Failed, "map artifact handle index exhausted"));
94
95 MapArtifactRecord record;
96 record.id = publication.id;
97 record.buildKey = std::string(publication.buildKey);
98 record.handle = MapArtifactHandle(nextIndex_, 1);
99 record.width = topology->width;
100 record.height = topology->height;
101 try {
102 record.cells.assign(topology->cells.begin(), topology->cells.end());
103 records_.reserve(records_.size() + 1);
105 std::make_unique<MapArtifactStage>(*this, std::move(record)));
106 } catch (...) {
108 eve::Diagnostic::error(eve::DiagnosticCode::Failed, "map artifact prepare allocation failed"));
109 }
110}
111
112void MapArtifactProvider::commit(MapArtifactRecord record) noexcept {
113 records_.push_back(std::move(record));
114 ++nextIndex_;
115}
116
118 const auto found =
119 std::find_if(records_.begin(), records_.end(), [id](const auto& record) { return record.id == id; });
120 return found == records_.end() ? nullptr : &*found;
121}
122
123std::optional<std::uint32_t> MapArtifactProvider::cell(eve::PersistentId id, std::int32_t x,
124 std::int32_t y) const noexcept {
125 const auto* record = find(id);
126 if (!record || x < 0 || y < 0 || x >= record->width || y >= record->height) return std::nullopt;
127 return record
128 ->cells[static_cast<std::size_t>(y) * static_cast<std::size_t>(record->width) + static_cast<std::size_t>(x)];
129}
130
132 records_.clear();
133 nextIndex_ = 0;
134 failPrepare_ = false;
135}
136
138 try {
139 eve::Value::Array records;
140 records.reserve(records_.size());
141 for (const auto& record : records_) {
143 cells.reserve(record.cells.size());
144 for (const auto value : record.cells) cells.emplace_back(std::int64_t(value));
146 item.emplace("artifactId", eve::Value(record.id.format()));
147 item.emplace("buildKey", eve::Value(record.buildKey));
148 item.emplace("handle", eve::Value(std::to_string(record.handle.packed())));
149 item.emplace("width", eve::Value(std::int64_t(record.width)));
150 item.emplace("height", eve::Value(std::int64_t(record.height)));
151 item.emplace("cells", eve::Value(std::move(cells)));
152 records.emplace_back(std::move(item));
153 }
155 state.emplace("provider", eve::Value("map.cpu-registry"));
156 state.emplace("version", eve::Value(std::int64_t(1)));
157 state.emplace("records", eve::Value(std::move(records)));
159 } catch (...) {
161 eve::Diagnostic::error(eve::DiagnosticCode::Failed, "map artifact snapshot allocation failed"));
162 }
163}
164
166 if (!records_.empty())
168 eve::Diagnostic::error(eve::DiagnosticCode::Conflict, "map artifact restore requires an empty registry"));
169 const auto* object = state.getIf<eve::Value::Object>();
170 const auto* provider = object ? member(*object, "provider") : nullptr;
171 const auto* providerName = provider ? provider->getIf<std::string>() : nullptr;
172 const auto* encodedRecords = object ? member(*object, "records") : nullptr;
173 const auto* records = encodedRecords ? encodedRecords->getIf<eve::Value::Array>() : nullptr;
174 if (!object || !providerName || *providerName != "map.cpu-registry" || !hasSupportedVersion(*object) || !records)
176 eve::Diagnostic::error(eve::DiagnosticCode::ParseError, "invalid map artifact provider state"));
177
178 std::vector<MapArtifactRecord> candidate;
179 std::unordered_set<eve::PersistentId> identities;
180 std::uint32_t next = 0;
181 try {
182 candidate.reserve(records->size());
183 for (const eve::Value& encoded : *records) {
184 const auto* item = encoded.getIf<eve::Value::Object>();
185 std::string idText;
186 std::string buildKey;
187 std::uint64_t packed = 0;
188 std::int64_t width = 0;
189 std::int64_t height = 0;
190 const auto* encodedCells = item ? member(*item, "cells") : nullptr;
191 const auto* cells = encodedCells ? encodedCells->getIf<eve::Value::Array>() : nullptr;
192 if (!item || !readString(*item, "artifactId", idText) || !readString(*item, "buildKey", buildKey) ||
193 !readU64(*item, "handle", packed) || !readI64(*item, "width", width) ||
194 !readI64(*item, "height", height) || width <= 0 || height <= 0 || !cells)
196 eve::Diagnostic::error(eve::DiagnosticCode::ParseError, "invalid map artifact record"));
197 const auto parsedId = eve::PersistentId::parse(idText);
198 const auto handle = MapArtifactHandle::fromPacked(packed);
199 if (!parsedId || parsedId->isNil() || handle.isInvalid() ||
200 width > std::numeric_limits<std::int32_t>::max() || height > std::numeric_limits<std::int32_t>::max() ||
201 !identities.emplace(*parsedId).second ||
202 static_cast<std::uint64_t>(width) * static_cast<std::uint64_t>(height) != cells->size())
204 eve::DiagnosticCode::ParseError, "invalid map artifact dimensions or identity"));
205 MapArtifactRecord record;
206 record.id = *parsedId;
207 record.buildKey = std::move(buildKey);
208 record.handle = handle;
209 record.width = static_cast<std::int32_t>(width);
210 record.height = static_cast<std::int32_t>(height);
211 record.cells.reserve(cells->size());
212 for (const eve::Value& value : *cells) {
213 const auto* cell = value.getIf<std::int64_t>();
214 if (!cell || *cell < 0 || *cell > std::numeric_limits<std::uint32_t>::max())
216 eve::Diagnostic::error(eve::DiagnosticCode::ParseError, "invalid map topology cell"));
217 record.cells.push_back(static_cast<std::uint32_t>(*cell));
218 }
219 next = std::max(next, handle.index() + 1u);
220 candidate.push_back(std::move(record));
221 }
222 } catch (...) {
224 eve::Diagnostic::error(eve::DiagnosticCode::Failed, "map artifact restore allocation failed"));
225 }
226 records_.swap(candidate);
227 nextIndex_ = next;
229}
230
232 static MapArtifactProvider provider;
233 return provider;
234}
235
236void registerMapArtifactProvider() { eve::cap::provide<eve::artifact::IMapArtifactAdapter>(&mapArtifactProvider()); }
237
238} // namespace eve::map
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
std::string output
std::uint32_t height
std::uint32_t width
std::string text
std::string name
std::string error
Definition Package.cpp:60
Topology topology
std::array< PixelCell, kPixelChunkSize *kPixelChunkSize > cells
PrimitiveHandle handle
bool found
Cell cell
float(ui::Theme::* member)[4]
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 constexpr RuntimeHandle fromPacked(std::uint64_t value) noexcept
Reconstructs a handle from an explicit packed boundary value.
static constexpr index_type invalidIndex
Reserved index value shared by all invalid handles.
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
std::map< std::string, Value > Object
Definition Value.h:34
std::vector< Value > Array
Definition Value.h:33
Value * find(const std::string &key) noexcept
Return an object member, or nullptr when absent.
Definition Value.cpp:124
A prepared consumer mutation with a non-throwing visibility boundary.
Id128 public API.
Definition Identity.h:112
constexpr bool isNil() const noexcept
Returns whether this value is the all-zero nil ID.
Definition Identity.h:176
static std::optional< Id128 > parse(std::string_view text) noexcept
Parses canonical UUID text.
Definition Identity.h:151
Real map-module provider for generated grid publication.
void clear() noexcept
Remove all records and reset the local handle allocator.
eve::Result< std::unique_ptr< eve::artifact::PreparedPublication > > prepare(const eve::artifact::PublicationView &publication) override
Stage a topology grid and copy its cells before commit.
const MapArtifactRecord * find(eve::PersistentId id) const noexcept
Find a committed map artifact; the pointer is borrowed. @ownership Borrowed from this provider; calle...
eve::Result< void > restoreState(const eve::Value &state) override
Replace the registry from validated topology state.
eve::Result< eve::Value > snapshotState() const override
Export map identity, build keys, handles and topology cells.
std::optional< std::uint32_t > cell(eve::PersistentId id, std::int32_t x, std::int32_t y) const noexcept
Return one semantic cell, or empty for an invalid coordinate.
void commit() noexcept override
Make the prepared mutation observable; the operation cannot fail.
void rollback() noexcept override
Discard the prepared mutation; idempotent and non-throwing.
MapArtifactStage(MapArtifactProvider &owner, MapArtifactRecord record)
Map-owned CPU registry provider for generated grid artifacts.
放置世界:格子占用(多通道)+ 地形语义 + 已放置建筑实例。 行为由 PlacementSystem 提供;本类暴露便于脚本绑定的薄封装方法。 坐标换算统一走 eve::grid(支持 rectang...
eve::RuntimeHandle< MapArtifactHandleTag > MapArtifactHandle
Generation-qualified handle for a map artifact record.
bool readI64(const eve::Value::Object &object, const char *name, std::int64_t &output)
void registerMapArtifactProvider()
Register the map provider in the common capability registry.
MapArtifactProvider & mapArtifactProvider() noexcept
Return the process-owned map artifact provider singleton.
bool readU64(const eve::Value::Object &object, const char *name, std::uint64_t &output)
bool readString(const eve::Value::Object &object, const char *name, std::string &output)
bool hasSupportedVersion(const eve::Value::Object &object) noexcept
Borrowed immutable view of one generated leaf.
Borrowed immutable view of one complete generated publication.
std::span< const PartView > parts
Queryable map record containing the copied semantic topology.
std::vector< std::uint32_t > cells