16 const auto found =
object.find(std::string(
name));
17 return found ==
object.end() ? nullptr : &
found->second;
23 if (!
text)
return false;
42 const auto*
boolean =
value->getIf<
bool>();
43 if (!
boolean)
return false;
61 if (
const auto* integer =
value.getIf<std::int64_t>())
62 number =
static_cast<double>(*integer);
63 else if (
const auto* real =
value.getIf<
double>())
67 if (!std::isfinite(
number) ||
number < -
static_cast<double>(std::numeric_limits<float>::max()) ||
68 number >
static_cast<double>(std::numeric_limits<float>::max()))
77 return array && array->size() == 3 && numericFloat((*array)[0],
output.x) && numericFloat((*array)[1],
output.y) &&
78 numericFloat((*array)[2],
output.z);
109 else if (
value ==
"requested")
111 else if (
value ==
"aligning")
113 else if (
value ==
"launching")
115 else if (
value ==
"climbing" ||
value ==
"traversing")
119 else if (
value ==
"landing")
121 else if (
value ==
"recovering")
123 else if (
value ==
"hanging")
125 else if (
value ==
"dropping")
127 else if (
value ==
"completed")
129 else if (
value ==
"cancelled")
131 else if (
value ==
"failed")
133 else if (
value ==
"balanced")
135 else if (
value ==
"swinging")
160 if (
value ==
"started")
162 else if (
value ==
"anchor_transition_started")
164 else if (
value ==
"anchor_reached")
166 else if (
value ==
"contact_left_hand")
168 else if (
value ==
"contact_right_hand")
170 else if (
value ==
"landed")
172 else if (
value ==
"hanging")
174 else if (
value ==
"dropped")
176 else if (
value ==
"completed")
178 else if (
value ==
"cancelled")
180 else if (
value ==
"failed")
187eve::Value eventValue(
const ClimbingEvent& event) {
189 metadata.reserve(event.metadata.size());
190 for (
const std::string&
value : event.metadata) metadata.emplace_back(
value);
193 {
"actionId",
event.actionId},
194 {
"tick", std::to_string(event.tick.value())},
195 {
"executionId", std::to_string(event.executionId.value())},
196 {
"metadata",
eve::Value(std::move(metadata))},
203 for (
const auto& event :
events)
values.push_back(eventValue(event));
210 return eve::Result<std::vector<ClimbingEvent>>::failure(
212 "pendingEvents", {},
"climbing.snapshot"));
213 std::vector<ClimbingEvent>
events;
214 events.reserve(array->size());
221 std::uint64_t
tick = 0;
223 if (!
object || !
readString(*
object,
"kind",
kind) || !readEventKind(
kind, event.kind) ||
224 !
readString(*
object,
"actionId", event.actionId) ||
event.actionId.empty() ||
229 "pendingEvents." + std::to_string(
index), {},
"climbing.snapshot"));
235 "pendingEvents." + std::to_string(
index) +
".metadata", {},
"climbing.snapshot"));
236 event.metadata.reserve(metadata->size());
238 const auto*
text = item.getIf<std::string>();
242 "pendingEvents." + std::to_string(
index) +
".metadata", {},
"climbing.snapshot"));
243 event.metadata.push_back(*
text);
248 if (!
first && event.tick < previousTick)
251 "pendingEvents." + std::to_string(
index) +
".tick", {},
"climbing.snapshot"));
253 previousTick =
event.tick;
254 events.push_back(std::move(event));
261 {
"actionId",
value.actionId},
262 {
"definitionGeneration", std::to_string(
value.definitionGeneration)},
263 {
"world", std::to_string(
value.world.packed())},
264 {
"obstacleBody", std::to_string(
value.obstacleBody.packed())},
265 {
"obstacleShape", std::to_string(
value.obstacleShape.packed())},
266 {
"obstacleBodyId",
value.obstacleBodyId},
267 {
"obstacleShapeId",
value.obstacleShapeId},
268 {
"ignoredBodyId",
value.ignoredBodyId},
269 {
"frontPoint", vecValue(
value.frontPoint)},
270 {
"topPoint", vecValue(
value.topPoint)},
271 {
"landingFeet", vecValue(
value.landingFeet)},
272 {
"surfaceNormal", vecValue(
value.surfaceNormal)},
273 {
"surfaceTangent", vecValue(
value.surfaceTangent)},
274 {
"leftHandAnchor", vecValue(
value.leftHandAnchor)},
275 {
"rightHandAnchor", vecValue(
value.rightHandAnchor)},
276 {
"bodyLocalTop", vecValue(
value.bodyLocalTop)},
277 {
"bodyLocalLanding", vecValue(
value.bodyLocalLanding)},
278 {
"obstacleHeight",
value.obstacleHeight},
279 {
"obstacleDepth",
value.obstacleDepth},
280 {
"gapDistance",
value.gapDistance},
281 {
"clearanceHeight",
value.clearanceHeight},
282 {
"slopeRadians",
value.slopeRadians},
283 {
"curvature",
value.curvature},
284 {
"supportShapeTag",
value.supportShapeTag},
285 {
"supportMaterialId",
value.supportMaterialId},
286 {
"probeRecipe",
static_cast<std::int64_t
>(
value.probeRecipe)},
287 {
"score",
value.score},
288 {
"kind",
static_cast<std::int64_t
>(
value.kind)},
289 {
"support",
static_cast<std::int64_t
>(
value.support)},
294 const ClimbingAnchorReservation& reservation) {
297 {
"graphHandle", std::to_string(
graph.packed())},
298 {
"graphOwnerEpoch", std::to_string(
graph.ownerEpoch)},
299 {
"graphId",
node.graphId},
300 {
"nodeId",
node.nodeId},
301 {
"nodeGraphGeneration", std::to_string(
node.graphGeneration)},
302 {
"reservationId", std::to_string(reservation.id.value())},
303 {
"reservationGraphGeneration", std::to_string(reservation.graphGeneration)},
304 {
"claimGeneration", std::to_string(reservation.claimGeneration)},
305 {
"slot",
static_cast<std::int64_t
>(reservation.slot)},
306 {
"agentId", std::to_string(reservation.occupant.agentId.value())},
307 {
"executionId", std::to_string(reservation.occupant.executionId.value())},
316 "execution.candidate", {},
"climbing.snapshot"));
317 ClimbingCandidate result;
318 std::uint64_t
world = 0,
body = 0,
shape = 0, definitionGeneration = 1;
319 std::int64_t bodyId = 0, shapeId = 0, ignoredBodyId = 0,
score = 0,
kind = 0, support = 0;
320 std::int64_t supportShapeTag = 0, supportMaterialId = 0, probeRecipe = 0;
327 if (!
readString(*
object,
"actionId", result.actionId) ||
328 (
field(*
object,
"definitionGeneration") &&
329 !
readUint64String(*
object,
"definitionGeneration", definitionGeneration)) ||
332 !readInt64(*
object,
"obstacleBodyId", bodyId) || bodyId < std::numeric_limits<int>::min() ||
333 bodyId > std::numeric_limits<int>::max() || !readInt64(*
object,
"obstacleShapeId", shapeId) ||
334 shapeId < std::numeric_limits<int>::min() || shapeId > std::numeric_limits<int>::max() ||
335 !readInt64(*
object,
"ignoredBodyId", ignoredBodyId) || ignoredBodyId < std::numeric_limits<int>::min() ||
336 ignoredBodyId > std::numeric_limits<int>::max() || !readVec(*
object,
"frontPoint", result.frontPoint) ||
337 !readVec(*
object,
"topPoint", result.topPoint) || !readVec(*
object,
"landingFeet", result.landingFeet) ||
338 !readVec(*
object,
"surfaceNormal", result.surfaceNormal) ||
339 !readVec(*
object,
"surfaceTangent", result.surfaceTangent) ||
340 !readVec(*
object,
"leftHandAnchor", result.leftHandAnchor) ||
341 !readVec(*
object,
"rightHandAnchor", result.rightHandAnchor) ||
342 !readVec(*
object,
"bodyLocalTop", result.bodyLocalTop) ||
343 !readVec(*
object,
"bodyLocalLanding", result.bodyLocalLanding) || !heightValue ||
344 !numericFloat(*heightValue, result.obstacleHeight) || !readInt64(*
object,
"score",
score) ||
345 !readInt64(*
object,
"kind",
kind) ||
kind < 0 ||
347 !readInt64(*
object,
"support", support) ||
351 "execution.candidate", {},
"climbing.snapshot"));
352 if ((snapshotVersion >= 4 && (!depthValue || !gapValue || !clearanceValue || !slopeValue || !curvatureValue ||
353 !
field(*
object,
"supportShapeTag") || !
field(*
object,
"supportMaterialId") ||
354 !
field(*
object,
"probeRecipe"))) ||
355 (depthValue && !numericFloat(*depthValue, result.obstacleDepth)) ||
356 (gapValue && !numericFloat(*gapValue, result.gapDistance)) ||
357 (clearanceValue && !numericFloat(*clearanceValue, result.clearanceHeight)) ||
358 (slopeValue && !numericFloat(*slopeValue, result.slopeRadians)) ||
359 (curvatureValue && !numericFloat(*curvatureValue, result.curvature)) ||
360 (
field(*
object,
"supportShapeTag") && !readInt64(*
object,
"supportShapeTag", supportShapeTag)) ||
361 supportShapeTag < std::numeric_limits<int>::min() || supportShapeTag > std::numeric_limits<int>::max() ||
362 (
field(*
object,
"supportMaterialId") && !readInt64(*
object,
"supportMaterialId", supportMaterialId)) ||
363 supportMaterialId < std::numeric_limits<int>::min() ||
364 supportMaterialId > std::numeric_limits<int>::max() ||
365 (
field(*
object,
"probeRecipe") && !readInt64(*
object,
"probeRecipe", probeRecipe)) || probeRecipe < 0 ||
369 "execution.candidate", {},
"climbing.snapshot"));
370 result.definitionGeneration = definitionGeneration;
374 result.obstacleBodyId =
static_cast<int>(bodyId);
375 result.obstacleShapeId =
static_cast<int>(shapeId);
376 result.ignoredBodyId =
static_cast<int>(ignoredBodyId);
377 result.score =
score;
379 result.supportShapeTag =
static_cast<int>(supportShapeTag);
380 result.supportMaterialId =
static_cast<int>(supportMaterialId);
382 result.support =
static_cast<HangSupport>(support);
398 {
"phase",
eve::Value(std::string(phaseName(phase_)))},
400 {
"definitionGeneration",
eve::Value(std::to_string(definitionGeneration_))},
401 {
"profile", std::move(profile).takeValue()},
402 {
"previousActionId",
eve::Value(previousActionId_)},
403 {
"nextExecutionId",
eve::Value(std::to_string(nextExecutionId_))},
404 {
"pendingEvents", eventArrayValue(pendingEvents_)}};
412 {
"executionId", std::to_string(execution_->executionId.value())},
413 {
"definitionGeneration", std::to_string(execution_->definitionGeneration)},
414 {
"action", std::move(
action).takeValue()},
415 {
"candidate", candidateValue(execution_->candidate)},
416 {
"startFeet", vecValue(execution_->startFeet)},
417 {
"currentFeet", vecValue(execution_->currentFeet)},
418 {
"lastPlannedFeet", vecValue(execution_->lastPlannedFeet)},
419 {
"elapsedNs", execution_->elapsed.nanoseconds()},
420 {
"durationNs", execution_->duration.nanoseconds()},
421 {
"lastTick", std::to_string(execution_->lastTick.value())},
422 {
"velocity", vecValue(execution_->velocity)},
423 {
"accumulatedResidual", vecValue(execution_->accumulatedResidual)},
424 {
"horizontalWarpUsed", execution_->horizontalWarpUsed},
425 {
"verticalWarpUsed", execution_->verticalWarpUsed},
426 {
"facingWarpUsed", execution_->facingWarpUsed},
427 {
"leftContactEmitted", execution_->leftContactEmitted},
428 {
"rightContactEmitted", execution_->rightContactEmitted},
429 {
"landContactReleased", execution_->landContactReleased},
430 {
"compactCollisionActive", execution_->compactCollisionActive},
431 {
"branchWindowOpen", execution_->branchWindowOpen},
432 {
"anchor", anchorValue(execution_->anchorGraph, execution_->anchorNode,
433 execution_->anchorReservation)},
444 std::string schemaId;
445 std::int64_t version = -1;
446 std::string phaseText;
447 std::string terminalCode;
448 std::string candidatePreviousActionId;
449 std::uint64_t candidateNextExecutionId = 1;
450 std::uint64_t candidateDefinitionGeneration = definitionGeneration_;
453 !readString(*
root,
"phase", phaseText) ||
454 (version >= 1 && !readString(*
root,
"terminalCode", terminalCode))) {
457 "climbing.restore.version_unsupported",
458 "schemaVersion", {},
"climbing.snapshot"));
460 "invalid climbing runtime snapshot envelope", {}, {},
461 "climbing.snapshot"));
463 if (version >= 4 && !readString(*
root,
"previousActionId", candidatePreviousActionId))
465 "invalid previous climbing action id",
466 "previousActionId", {},
"climbing.snapshot"));
467 if (field(*
root,
"nextExecutionId") && !readUint64String(*
root,
"nextExecutionId", candidateNextExecutionId))
469 "invalid next climbing execution id",
470 "nextExecutionId", {},
"climbing.snapshot"));
471 if (field(*
root,
"definitionGeneration") &&
472 (!readUint64String(*
root,
"definitionGeneration", candidateDefinitionGeneration) ||
473 candidateDefinitionGeneration == 0))
475 "invalid climbing definition generation",
476 "definitionGeneration", {},
"climbing.snapshot"));
481 candidateProfile = std::move(decodedProfile).takeValue();
484 if (!readPhase(phaseText, candidatePhase))
490 "runtime snapshot execution field is required",
491 "execution", {},
"climbing.snapshot"));
492 std::optional<Execution> candidateExecution;
493 if (!executionValue->
isNull()) {
497 if (!
state || !actionValue || !candidateValueField)
499 "invalid climbing execution object",
"execution",
500 {},
"climbing.snapshot"));
503 auto candidate = readCandidate(*candidateValueField, version);
507 std::uint64_t executionDefinitionGeneration = candidateDefinitionGeneration;
510 "invalid climbing execution id",
511 "execution.executionId", {},
"climbing.snapshot"));
513 if (field(*
state,
"definitionGeneration") &&
514 (!readUint64String(*
state,
"definitionGeneration", executionDefinitionGeneration) ||
515 executionDefinitionGeneration == 0))
518 "execution.definitionGeneration", {},
"climbing.snapshot"));
519 parsed.definitionGeneration = executionDefinitionGeneration;
520 parsed.action = std::move(
action).takeValue();
521 parsed.candidate = std::move(candidate).takeValue();
522 std::int64_t elapsedNs = 0, durationNs = 0;
523 std::uint64_t lastTick = 0;
524 if (parsed.action.id != parsed.candidate.actionId ||
525 (field(*
state,
"definitionGeneration") &&
526 parsed.candidate.definitionGeneration != parsed.definitionGeneration) ||
527 !readVec(*
state,
"startFeet", parsed.startFeet) ||
528 !readVec(*
state,
"currentFeet", parsed.currentFeet) ||
529 !readVec(*
state,
"lastPlannedFeet", parsed.lastPlannedFeet) || !readInt64(*
state,
"elapsedNs", elapsedNs) ||
530 elapsedNs < 0 || !readInt64(*
state,
"durationNs", durationNs) || durationNs <= 0 ||
531 !readUint64String(*
state,
"lastTick", lastTick) || !readVec(*
state,
"velocity", parsed.velocity) ||
532 !readVec(*
state,
"accumulatedResidual", parsed.accumulatedResidual) ||
533 !readOptionalFloat(*
state,
"horizontalWarpUsed", parsed.horizontalWarpUsed) ||
534 !readOptionalFloat(*
state,
"verticalWarpUsed", parsed.verticalWarpUsed) ||
535 !readOptionalFloat(*
state,
"facingWarpUsed", parsed.facingWarpUsed) || parsed.horizontalWarpUsed < 0.f ||
536 parsed.verticalWarpUsed < 0.f || parsed.facingWarpUsed < 0.f ||
537 !readBool(*
state,
"leftContactEmitted", parsed.leftContactEmitted,
false, version != 0) ||
538 !readBool(*
state,
"rightContactEmitted", parsed.rightContactEmitted,
false, version != 0) ||
539 !readBool(*
state,
"landContactReleased", parsed.landContactReleased,
false,
false) ||
540 !readBool(*
state,
"compactCollisionActive", parsed.compactCollisionActive,
false,
false) ||
541 !readBool(*
state,
"branchWindowOpen", parsed.branchWindowOpen,
false,
false))
544 {},
"climbing.snapshot"));
546 if (version >= 3 && !anchorField)
548 "runtime snapshot anchor field is required",
549 "execution.anchor", {},
"climbing.snapshot"));
550 if (anchorField && !anchorField->
isNull()) {
554 "execution.anchor", {},
"climbing.snapshot"));
556 std::uint64_t graphHandle = 0, graphOwnerEpoch = 0, nodeGraphGeneration = 0;
557 std::uint64_t reservationId = 0, reservationGraphGeneration = 0, claimGeneration = 0;
558 std::uint64_t agentId = 0, occupantExecutionId = 0;
559 std::int64_t slot = -1;
560 std::string graphId,
nodeId;
561 if (!
anchor || !readUint64String(*
anchor,
"graphHandle", graphHandle) ||
562 !readUint64String(*
anchor,
"graphOwnerEpoch", graphOwnerEpoch) || graphOwnerEpoch == 0 ||
563 !readString(*
anchor,
"graphId", graphId) || graphId.empty() ||
565 !readUint64String(*
anchor,
"nodeGraphGeneration", nodeGraphGeneration) ||
566 nodeGraphGeneration == 0 || !readUint64String(*
anchor,
"reservationId", reservationId) ||
567 reservationId == 0 ||
568 !readUint64String(*
anchor,
"reservationGraphGeneration", reservationGraphGeneration) ||
569 reservationGraphGeneration == 0 ||
570 !readUint64String(*
anchor,
"claimGeneration", claimGeneration) || claimGeneration == 0 ||
571 !readInt64(*
anchor,
"slot", slot) || slot < 0 ||
572 slot >
static_cast<std::int64_t
>(std::numeric_limits<std::uint32_t>::max()) ||
573 !readUint64String(*
anchor,
"agentId", agentId) || agentId == 0 ||
574 !readUint64String(*
anchor,
"executionId", occupantExecutionId) || occupantExecutionId == 0)
577 "execution.anchor", {},
"climbing.snapshot"));
579 parsed.anchorGraph.ownerEpoch = graphOwnerEpoch;
580 parsed.anchorNode = {std::move(graphId), std::move(
nodeId), nodeGraphGeneration};
582 claimGeneration, parsed.anchorNode.nodeId,
static_cast<std::uint32_t
>(slot),
584 if (!parsed.anchorGraph.isValid() || nodeGraphGeneration != reservationGraphGeneration ||
585 parsed.executionId != parsed.anchorReservation.occupant.executionId)
587 "runtime anchor identities are inconsistent",
588 "execution.anchor", {},
"climbing.snapshot"));
593 if (parsed.duration != parsed.action.duration || parsed.elapsed > parsed.duration)
595 "execution timing disagrees with pinned action",
596 "execution.durationNs", {},
"climbing.snapshot"));
597 const bool graphBound = parsed.anchorGraph.isValid();
598 if (
world.runtimeHandle() != parsed.candidate.world || !
world.findBody(parsed.candidate.obstacleBody) ||
599 (!graphBound && !
world.findShape(parsed.candidate.obstacleShape)))
601 "climbing restore target link is stale",
602 "execution.candidate", {},
"climbing.snapshot"));
605 if (!
graph.isBound() ||
graph->body() != parsed.candidate.obstacleBody)
608 "execution.anchor.graph", {},
"climbing.snapshot"));
609 auto resolved =
graph->resolveNode(
world, parsed.anchorNode);
612 auto reservation =
graph->validateReservation(parsed.anchorReservation);
616 candidateExecution = std::move(parsed);
618 if (activePhase(candidatePhase) != candidateExecution.has_value())
620 "active phase and execution presence disagree",
621 "execution", {},
"climbing.snapshot"));
622 if (!field(*
root,
"nextExecutionId")) {
623 candidateNextExecutionId = candidateExecution ? candidateExecution->executionId.value() + 1 : 1;
625 if (candidateNextExecutionId == 0 ||
626 (candidateExecution && (candidateExecution->executionId.isZero() ||
629 "next execution id must follow the restored execution",
630 "nextExecutionId", {},
"climbing.snapshot"));
631 std::vector<ClimbingEvent> candidateEvents;
632 if (
const eve::Value* eventValue = field(*
root,
"pendingEvents")) {
633 auto parsedEvents = readEvents(*eventValue, candidateNextExecutionId);
635 candidateEvents = std::move(parsedEvents).takeValue();
636 }
else if (version >= 2) {
638 "runtime snapshot pendingEvents field is required",
639 "pendingEvents", {},
"climbing.snapshot"));
642 if (execution_ && execution_->anchorGraph.isValid() &&
643 (!candidateExecution || execution_->anchorGraph != candidateExecution->anchorGraph ||
644 execution_->anchorReservation.id != candidateExecution->anchorReservation.id ||
645 execution_->anchorReservation.claimGeneration != candidateExecution->anchorReservation.claimGeneration))
648 {},
"climbing.snapshot"));
649 if (candidateExecution && candidateExecution->anchorGraph.isValid()) {
650 const bool alreadyOwned = execution_ && execution_->anchorGraph == candidateExecution->anchorGraph &&
651 execution_->anchorReservation.id == candidateExecution->anchorReservation.id &&
652 execution_->anchorReservation.claimGeneration ==
653 candidateExecution->anchorReservation.claimGeneration;
656 if (!
graph.isBound())
659 "execution.anchor.graph", {},
"climbing.snapshot"));
660 auto claimed =
graph->restoreReservation(candidateExecution->anchorReservation);
662 candidateExecution->anchorReservation = std::move(claimed).takeValue();
667 phase_ = candidatePhase;
668 profile_ = std::move(candidateProfile);
669 terminalCode_ = std::move(terminalCode);
670 execution_ = std::move(candidateExecution);
671 previousActionId_ = std::move(candidatePreviousActionId);
672 nextExecutionId_ = candidateNextExecutionId;
673 definitionGeneration_ = candidateDefinitionGeneration;
674 pendingEvents_ = std::move(candidateEvents);
675 validatedAnimationActions_.clear();
676 lastCandidates_.clear();
677 lastDebugQueries_.clear();
678 lastEvidence_.clear();
679 motionEvidence_.clear();
eve::action::ActionExecutionId executionId
Versioned, lossless codecs for climbing definitions.
Deterministic climbing/parkour planning and capsule-constrained execution.
std::map< std::string, Var > values
std::map< std::string, std::vector< std::string > > graph
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.
static constexpr Duration fromNanoseconds(std::int64_t nanoseconds) noexcept
Construct an exact duration from nanoseconds.
Move-only operation result carrying either a value or Status.
static Result success(T value)
Construct a successful result owning value.
static Result failure(Status status)
Construct a failed result from a structured status.
static constexpr RuntimeHandle fromPacked(std::uint64_t value) noexcept
Reconstructs a handle from an explicit packed boundary value.
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
The canonical owning dynamic value used by data-facing protocols.
std::map< std::string, Value > Object
static Value array(Array value)
Compatibility factory for an array value.
std::vector< Value > Array
bool isNull() const noexcept
Return true when this value is null.
static Value object(Object value)
Compatibility factory for an object value.
const T * getIf() const noexcept
Return a typed pointer, or nullptr when the kind differs.
static constexpr std::int64_t SnapshotSchemaVersion
Current runtime snapshot version; v3 is N-1 and historical v2/v1/v0 remain migratable.
eve::Result< eve::Value > snapshot() const
Captures deterministic runtime state; debug candidates and final bone poses are excluded.
eve::Result< void > restore(const eve::Value &value, physics::World3D &world)
Restores a fully parsed candidate atomically after revalidating all process-local Physics links.
ClimbingExecutionId executionId() const noexcept
Current execution identity, or zero when no execution is active or retained.
static constexpr std::string_view SnapshotSchemaId
Stable schema id for owning runtime snapshots.
static constexpr std::size_t PendingEventCapacity
Hard bound for undelivered post-simulation events owned by one runtime.
static eve::script::Borrowed< ClimbingAnchorGraphInstance > resolveAnchorGraph(ClimbingAnchorGraphHandleRef reference) noexcept
Resolves a live graph instance as a synchronous non-owning observation.
constexpr std::uint64_t value() const noexcept
Returns the underlying value at an explicit protocol boundary.
static constexpr StrongUint64 zero() noexcept
Returns the zero value for this strong type.
Box3D rigid-body world. Script coordinates are meters (Box3D native), unlike 2D World which uses pixe...
const char * defaultValue
std::string eventKindName(EventKind kind)
Returns the stable lowercase name of an event kind.
eve::detail::StrongUint64< detail::ClimbingExecutionIdTag > ClimbingExecutionId
Stable non-zero identity assigned when a climbing selection transaction commits.
eve::Result< ClimbingActionDefinition > decodeClimbingActionDefinition(const eve::Value &value)
Decode and validate one action without partially mutating a registry.
eve::Result< eve::Value > encodeClimbingProfileDefinition(const ClimbingProfileDefinition &profile)
Encode one validated profile and all nested actions into canonical schema v4 data.
eve::Result< ClimbingProfileDefinition > decodeClimbingProfileDefinition(const eve::Value &value)
Decode and validate an owning profile candidate transactionally.
ClimbingPhase
Execution lifecycle visible to gameplay and animation adapters.
eve::detail::StrongUint64< detail::ClimbingAnchorReservationIdTag > ClimbingAnchorReservationId
Stable non-zero identity of one live anchor-slot reservation.
eve::Result< eve::Value > encodeClimbingActionDefinition(const ClimbingActionDefinition &action)
Encode one validated action into canonical schema v4 data.
HangSupport
Evidence describing whether a hanging pose has foot support.
eve::script::RuntimeHandleRef< ClimbingAnchorGraphHandleTag > ClimbingAnchorGraphHandleRef
Generation- and module-epoch-qualified anchor graph instance reference.
ClimbingEventKind
Stable semantic event emitted by the authoritative climbing lifecycle.
@ AnchorTransitionStarted
ClimbingActionKind
Data-driven action family; stable action identity remains the definition id.
eve::detail::StrongUint64< detail::ClimbingAnchorAgentIdTag > ClimbingAnchorAgentId
Stable non-zero identity of the character/agent that owns graph occupancy.
ClimbingProbeRecipe
Semantic query family used to produce action candidates.
bool readString(const eve::Value::Object &object, const char *name, std::string &output)
const EditorValue * field(const EditorValue &value, const char *name)
bool readUint64String(const eve::Value::Object &object, const char *name, std::uint64_t &output)
std::string_view phaseName(BattlePhase phase) noexcept
Return the stable protocol spelling of a battle phase.
detail::StrongUint64< detail::SimulationTickTag > SimulationTick
Deterministic simulation time step; it is not wall-clock time.
Runtime profile controlling capsule geometry and probe limits.