载入中...
搜索中...
未找到
PixelWorldControl.cpp
浏览该文件的文档.
2
4
5#include <algorithm>
6#include <chrono>
7#include <deque>
8#include <unordered_map>
9
10namespace eve::pixelworld {
11namespace {
12
13PixelWorldSummary summarize(const PixelWorld& world) {
14 return {world.worldLink(), world.seed(), world.revision(), world.tickValue(),
15 world.lastEditSequence(), std::uint32_t(world.chunkCount()),
16 std::uint32_t(world.activeChunkCount()), world.isPaused()};
17}
18
19} // namespace
20
22 std::unordered_map<std::uint64_t, PixelWorld*> worlds;
23 std::unordered_map<std::uint64_t, std::deque<PixelWorldPerformanceSample>> samples;
24};
25
26PixelWorldControlService::Impl& PixelWorldControlService::impl() const {
27 static auto* state = new Impl;
28 return *state;
29}
30
35
36void PixelWorldControlService::registerWorld(PixelWorld& world) {
37 impl().worlds.insert_or_assign(world.worldLink().world, &world);
38}
39
40void PixelWorldControlService::unregisterWorld(const PixelWorld& world) noexcept {
41 const auto found = impl().worlds.find(world.worldLink().world);
42 if (found != impl().worlds.end() && found->second == &world) {
43 impl().worlds.erase(found);
44 impl().samples.erase(world.worldLink().world);
45 }
46}
47
48void PixelWorldControlService::rebindWorld(const PixelWorld* previous,
49 PixelWorld& replacement) noexcept {
50 auto& worlds = impl().worlds;
51 const auto found = worlds.find(replacement.worldLink().world);
52 if (found != worlds.end() && found->second == previous) found->second = &replacement;
53}
54
55PixelWorld* PixelWorldControlService::find(std::uint64_t worldId) const noexcept {
56 const auto found = impl().worlds.find(worldId);
57 return found == impl().worlds.end() ? nullptr : found->second;
58}
59
60void PixelWorldControlService::recordStep(std::uint64_t worldId, const StepStats& stats,
61 std::uint64_t elapsedMicroseconds) {
62 auto& samples = impl().samples[worldId];
63 samples.push_back({stats.tick.value(), elapsedMicroseconds, stats});
64 if (samples.size() > 256) samples.pop_front();
65}
66
67std::vector<PixelWorldSummary> PixelWorldControlService::worlds() const {
68 std::vector<PixelWorldSummary> result;
69 result.reserve(impl().worlds.size());
70 for (const auto& [id, world] : impl().worlds) result.push_back(summarize(*world));
71 std::sort(result.begin(), result.end(), [](const auto& a, const auto& b) {
72 return a.link.world < b.link.world;
73 });
74 return result;
75}
76
78 const PixelWorld* value = find(worldId);
81 eve::DiagnosticCode::NotFound, "PixelWorld is not live", "world", {}, "pixelworld.control"));
82}
83
84eve::Result<void> PixelWorldControlService::setPaused(std::uint64_t worldId, bool paused) {
85 PixelWorld* value = find(worldId);
86 if (!value)
88 eve::DiagnosticCode::NotFound, "PixelWorld is not live", "world", {}, "pixelworld.control"));
89 value->setPaused(paused);
91}
92
94 std::uint32_t count) {
95 PixelWorld* value = find(worldId);
96 if (!value)
98 eve::DiagnosticCode::NotFound, "PixelWorld is not live", "world", {}, "pixelworld.control"));
99 if (count == 0 || count > 1024)
101 eve::DiagnosticCode::InvalidArgument, "step count must be in [1, 1024]", "count", {},
102 "pixelworld.control"));
103 PixelWorldStepReceipt receipt;
104 receipt.world = worldId;
105 receipt.steps = count;
106 receipt.firstTick = value->tickValue() + 1;
107 const auto start = std::chrono::steady_clock::now();
108 for (std::uint32_t index = 0; index < count; ++index) {
109 auto advanced = value->advanceImpl(eve::SimulationTick(value->tickValue() + 1), nullptr);
110 if (!advanced.ok()) return eve::Result<PixelWorldStepReceipt>::failure(advanced.status());
111 receipt.finalStep = advanced.value();
112 }
113 receipt.lastTick = value->tickValue();
114 receipt.elapsedMicroseconds = std::uint64_t(std::chrono::duration_cast<std::chrono::microseconds>(
115 std::chrono::steady_clock::now() - start)
116 .count());
118}
119
121 std::uint64_t worldId, const PixelEditCommand& command) {
122 PixelWorld* value = find(worldId);
123 return value ? value->applyEdit(command)
125 eve::DiagnosticCode::NotFound, "PixelWorld is not live", "world", {}, "pixelworld.control"));
126}
127
129 std::uint64_t worldId, std::string_view catalogJson,
130 std::uint64_t expectedFingerprint) {
131 PixelWorld* value = find(worldId);
132 if (!value)
134 eve::DiagnosticCode::NotFound, "PixelWorld is not live", "world", {}, "pixelworld.control"));
135 auto catalog = decodeMaterialCatalogJson(catalogJson);
136 if (!catalog.ok())
138 return value->reloadMaterialCatalog(std::move(catalog).value(), expectedFingerprint);
139}
140
142 std::uint64_t worldId, PixelChunkRegion region) const {
143 const PixelWorld* value = find(worldId);
144 return value ? value->chunkDiagnostics(region)
146 eve::DiagnosticCode::NotFound, "PixelWorld is not live", "world", {}, "pixelworld.control"));
147}
148
150PixelWorldControlService::performanceSamples(std::uint64_t worldId, std::uint32_t limit) const {
151 if (!find(worldId))
153 eve::DiagnosticCode::NotFound, "PixelWorld is not live", "world", {}, "pixelworld.control"));
154 if (limit == 0 || limit > 256)
156 eve::DiagnosticCode::InvalidArgument, "sample limit must be in [1, 256]", "limit", {},
157 "pixelworld.control"));
158 const auto found = impl().samples.find(worldId);
159 if (found == impl().samples.end())
161 const auto& samples = found->second;
162 const std::size_t begin = samples.size() > limit ? samples.size() - limit : 0;
163 std::vector<PixelWorldPerformanceSample> result(samples.begin() + std::ptrdiff_t(begin),
164 samples.end());
166 std::move(result));
167}
168
170 std::uint64_t worldId) const {
171 const PixelWorld* value = find(worldId);
172 return value ? value->saveSnapshot()
174 eve::DiagnosticCode::NotFound, "PixelWorld is not live", "world", {}, "pixelworld.control"));
175}
176
178 std::uint64_t worldId, std::span<const std::byte> bytes) {
179 PixelWorld* value = find(worldId);
180 return value ? value->restoreSnapshot(bytes)
182 eve::DiagnosticCode::NotFound, "PixelWorld is not live", "world", {}, "pixelworld.control"));
183}
184
185} // namespace eve::pixelworld
double value
Duration start
void * service
void * impl
std::uint64_t bytes
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
graphics::Canvas * previous
OnnxTransferStats stats
Definition OnnxGpgpu.cpp:56
World3D * world
float begin
bool found
std::uint32_t count
int limit
Definition TreeMesh.cpp:164
uint32_t index
std::unordered_map< PhysicsWorldHandle::index_type, World3D * > worlds
Definition World3D.cpp:164
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
Main-thread-affine control surface shared by editor, CLI and MCP adapters.
eve::Result< void > restoreSnapshot(std::uint64_t worldId, std::span< const std::byte > bytes)
Transactionally restore a captured world snapshot.
eve::Result< std::vector< std::byte > > captureSnapshot(std::uint64_t worldId) const
Capture an owning canonical world snapshot.
eve::Result< PixelWorldStepReceipt > step(std::uint64_t worldId, std::uint32_t count=1)
Advance a live world explicitly even while paused; count is limited to 1024.
eve::Result< PixelCatalogReloadReceipt > reloadMaterialCatalog(std::uint64_t worldId, std::string_view catalogJson, std::uint64_t expectedFingerprint)
Validate JSON and transactionally hot-reload a compatible paused world Catalog.
eve::Result< PixelEditReceipt > applyEdit(std::uint64_t worldId, const PixelEditCommand &command)
Apply the world's canonical strictly sequenced edit operation.
eve::Result< std::vector< PixelChunkDiagnostic > > chunkDiagnostics(std::uint64_t worldId, PixelChunkRegion region) const
Copy a bounded read-only Chunk diagnostic region.
eve::Result< void > setPaused(std::uint64_t worldId, bool paused)
Pause or resume one live world.
eve::Result< std::vector< PixelWorldPerformanceSample > > performanceSamples(std::uint64_t worldId, std::uint32_t limit=120) const
Copy up to the latest 256 simulation performance samples.
eve::Result< PixelWorldSummary > world(std::uint64_t worldId) const
Query one live world summary.
std::vector< PixelWorldSummary > worlds() const
Return canonical world-id-ordered summaries of all live worlds.
Sparse, chunked, deterministic 2D falling-material world.
Definition PixelWorld.h:224
eve::Result< MaterialCatalog > decodeMaterialCatalogJson(std::string_view json)
Decode and validate schema eve.pixelworld.material-catalog version 1.
PixelWorldControlService & pixelWorldControlService()
Process-lifetime PixelWorld tooling registry.
Inclusive finite rectangle expressed in Chunk coordinates.
Definition PixelWorld.h:104
Owning replayable edit command. Sequence must be exactly previous + 1.
Definition PixelWorld.h:155
std::unordered_map< std::uint64_t, PixelWorld * > worlds
std::unordered_map< std::uint64_t, std::deque< PixelWorldPerformanceSample > > samples
Receipt for an explicit bounded tooling step.