载入中...
搜索中...
未找到
GameState.cpp
浏览该文件的文档.
1#include "rpg/GameState.h"
2
3#include "common/Value.h"
4
5#include <cmath>
6
7namespace {
8
10 const std::string &path) {
11 if (!value || !value->isObject())
13 eve::Diagnostic::error(eve::DiagnosticCode::ParseError, "game state field must be an object", path));
14 std::unordered_map<std::string, double> result;
15 for (const auto &key : value->keys()) {
16 const eve::Value *item = value->find(key);
17 if (!item || !item->isNumeric())
19 eve::DiagnosticCode::ParseError, "game state variable must be numeric", path + "." + key));
20 const double number = item->isInt64() ? static_cast<double>(item->asInt()) : item->asDouble();
21 if (!std::isfinite(number))
23 eve::DiagnosticCode::InvalidArgument, "game state variable must be finite", path + "." + key));
24 result.emplace(key, number);
25 }
26 return eve::Result<std::unordered_map<std::string, double>>::success(std::move(result));
27}
28
30 const std::string &path) {
31 if (!value || !value->isObject())
33 eve::Diagnostic::error(eve::DiagnosticCode::ParseError, "game state field must be an object", path));
34 std::unordered_map<std::string, std::string> result;
35 for (const auto &key : value->keys()) {
36 const eve::Value *item = value->find(key);
37 if (!item || !item->isString())
39 eve::DiagnosticCode::ParseError, "game state string fact must be a string", path + "." + key));
40 result.emplace(key, item->asString());
41 }
42 return eve::Result<std::unordered_map<std::string, std::string>>::success(std::move(result));
43}
44
45} // namespace
46
47namespace eve::rpg {
48
49void GameState::setSwitch(const std::string &name, bool on) { switches_[name] = on; }
50
51void GameState::switchOn(const std::string &name) { switches_[name] = true; }
52
53void GameState::switchOff(const std::string &name) { switches_[name] = false; }
54
55bool GameState::isSwitchOn(const std::string &name) const {
56 auto it = switches_.find(name);
57 return it != switches_.end() && it->second;
58}
59
60void GameState::setVariable(const std::string &name, double value) { variables_[name] = value; }
61
62double GameState::getVariable(const std::string &name) const {
63 auto it = variables_.find(name);
64 return it == variables_.end() ? 0.0 : it->second;
65}
66
67void GameState::addVariable(const std::string &name, double delta) {
68 variables_[name] = getVariable(name) + delta;
69}
70
71void GameState::setSelfVariable(const std::string &scope, const std::string &name, double value) {
72 selfVariables_[scope][name] = value;
73}
74
75double GameState::getSelfVariable(const std::string &scope, const std::string &name) const {
76 auto it = selfVariables_.find(scope);
77 if (it == selfVariables_.end()) return 0.0;
78 auto vit = it->second.find(name);
79 return vit == it->second.end() ? 0.0 : vit->second;
80}
81
82bool GameState::hasSelfVariable(const std::string &scope, const std::string &name) const {
83 auto it = selfVariables_.find(scope);
84 if (it == selfVariables_.end()) return false;
85 return it->second.find(name) != it->second.end();
86}
87
88void GameState::setSelfString(const std::string &scope, const std::string &name, std::string value) {
89 selfStrings_[scope][name] = std::move(value);
90}
91
92std::string GameState::getSelfString(const std::string &scope, const std::string &name) const {
93 auto it = selfStrings_.find(scope);
94 if (it == selfStrings_.end()) return {};
95 auto sit = it->second.find(name);
96 return sit == it->second.end() ? std::string{} : sit->second;
97}
98
99bool GameState::hasSelfString(const std::string &scope, const std::string &name) const {
100 auto it = selfStrings_.find(scope);
101 if (it == selfStrings_.end()) return false;
102 return it->second.find(name) != it->second.end();
103}
104
105void GameState::clearSelfString(const std::string &scope, const std::string &name) {
106 auto it = selfStrings_.find(scope);
107 if (it == selfStrings_.end()) return;
108 it->second.erase(name);
109 if (it->second.empty()) selfStrings_.erase(it);
110}
111
113 switches_.clear();
114 variables_.clear();
115 selfVariables_.clear();
116 selfStrings_.clear();
117}
118
120 eve::Value::Object switches;
121 for (const auto &[name, on] : switches_) switches.emplace(name, eve::Value(on));
122 eve::Value::Object variables;
123 for (const auto &[name, value] : variables_) variables.emplace(name, eve::Value(value));
124 eve::Value::Object scoped;
125 for (const auto &[scope, values] : selfVariables_) {
126 eve::Value::Object encoded;
127 for (const auto &[name, value] : values) encoded.emplace(name, eve::Value(value));
128 scoped.emplace(scope, eve::Value(std::move(encoded)));
129 }
130 eve::Value::Object scopedStrings;
131 for (const auto &[scope, values] : selfStrings_) {
132 eve::Value::Object encoded;
133 for (const auto &[name, value] : values) encoded.emplace(name, eve::Value(value));
134 scopedStrings.emplace(scope, eve::Value(std::move(encoded)));
135 }
137 root.emplace("schema", eve::Value("eve.rpg.game-state"));
138 root.emplace("selfStrings", eve::Value(std::move(scopedStrings)));
139 root.emplace("selfVariables", eve::Value(std::move(scoped)));
140 root.emplace("switches", eve::Value(std::move(switches)));
141 root.emplace("variables", eve::Value(std::move(variables)));
142 root.emplace("version", eve::Value(1));
143 return eve::Value(std::move(root)).toJson();
144}
145
147 auto parsed = eve::Value::fromJson(json);
148 if (!parsed.ok()) return eve::Result<void>::failure(parsed.status());
149 const eve::Value &root = parsed.value();
150 if (!root.isObject())
152 eve::Diagnostic::error(eve::DiagnosticCode::ParseError, "game state root must be an object", "$."));
153 const eve::Value *schema = root.find("schema");
154 if (!schema || !schema->isString() || schema->asString() != "eve.rpg.game-state")
156 eve::DiagnosticCode::InvalidArgument, "snapshot does not belong to RPG GameState", "$.schema"));
157 const eve::Value *version = root.find("version");
158 if (!version || !version->isInt64() || version->asInt() != 1)
160 eve::DiagnosticCode::UnknownVersion, "unsupported RPG GameState snapshot version", "$.version"));
161
162 const eve::Value *switches = root.find("switches");
163 if (!switches || !switches->isObject())
165 eve::DiagnosticCode::ParseError, "game state switches must be an object", "$.switches"));
166 std::unordered_map<std::string, bool> candidateSwitches;
167 for (const auto &key : switches->keys()) {
168 const eve::Value *item = switches->find(key);
169 if (!item || !item->isBool())
171 eve::DiagnosticCode::ParseError, "game state switch must be boolean", "$.switches." + key));
172 candidateSwitches.emplace(key, item->asBool());
173 }
174
175 auto candidateVariables = parseNumbers(root.find("variables"), "$.variables");
176 if (!candidateVariables.ok()) return eve::Result<void>::failure(candidateVariables.status());
177 const eve::Value *scoped = root.find("selfVariables");
178 if (!scoped || !scoped->isObject())
180 eve::DiagnosticCode::ParseError, "game state selfVariables must be an object", "$.selfVariables"));
181 std::unordered_map<std::string, std::unordered_map<std::string, double>> candidateScoped;
182 for (const auto &scope : scoped->keys()) {
183 auto values = parseNumbers(scoped->find(scope), "$.selfVariables." + scope);
184 if (!values.ok()) return eve::Result<void>::failure(values.status());
185 candidateScoped.emplace(scope, std::move(values).takeValue());
186 }
187
188 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> candidateStrings;
189 if (const eve::Value *scopedStrings = root.find("selfStrings"); scopedStrings != nullptr) {
190 if (!scopedStrings->isObject())
192 eve::DiagnosticCode::ParseError, "game state selfStrings must be an object", "$.selfStrings"));
193 for (const auto &scope : scopedStrings->keys()) {
194 auto values = parseStrings(scopedStrings->find(scope), "$.selfStrings." + scope);
195 if (!values.ok()) return eve::Result<void>::failure(values.status());
196 candidateStrings.emplace(scope, std::move(values).takeValue());
197 }
198 }
199
200 switches_ = std::move(candidateSwitches);
201 variables_ = std::move(candidateVariables).takeValue();
202 selfVariables_ = std::move(candidateScoped);
203 selfStrings_ = std::move(candidateStrings);
205}
206
208 static GameState g;
209 return g;
210}
211
212} // namespace eve::rpg
double value
int root
Definition AnimSmr.cpp:119
std::map< std::string, Var > values
全局游戏状态:开关(bool)、变量(数字)、独立变量(按作用域)。
tensor::Graph g
Definition GpuGraph.cpp:7
std::uint32_t key
JobScope scope
std::string name
std::string path
Definition PlayHost.cpp:110
double number
Owning, renderer-independent dynamic values.
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
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
Result< std::string > toJson() const
Serialize this value as deterministic compact JSON.
Definition Value.cpp:67
const std::string & asString() const
Return the string payload; the caller must have checked the kind.
Definition Value.cpp:87
bool isInt64() const noexcept
Return true when this value is an Int64.
Definition Value.h:91
static Result< Value > fromJson(std::string_view json)
Parse one strict JSON value into an owning Value.
Definition Value.cpp:57
std::map< std::string, Value > Object
Definition Value.h:34
bool isNumeric() const noexcept
Return whether this value is an integer or finite number.
Definition Value.h:159
std::vector< std::string > keys() const
Return object member names in deterministic order.
Definition Value.cpp:138
bool isString() const noexcept
Return true when this value is a string.
Definition Value.h:95
std::int64_t asInt() const
Return the Int64 payload; the caller must have checked the kind.
Definition Value.cpp:69
bool asBool() const
Return the boolean payload; the caller must have checked the kind.
Definition Value.cpp:81
bool isBool() const noexcept
Return true when this value is a boolean.
Definition Value.h:89
bool isObject() const noexcept
Return true when this value is an object.
Definition Value.h:99
Value * find(const std::string &key) noexcept
Return an object member, or nullptr when absent.
Definition Value.cpp:124
一份游戏状态(开关/变量/独立变量)。
Definition GameState.h:25
double getVariable(const std::string &name) const
Returns the variable.
Definition GameState.cpp:62
void clearSelfString(const std::string &scope, const std::string &name)
Remove one scoped string fact; no-op when absent.
void addVariable(const std::string &name, double delta)
Adds variable.
Definition GameState.cpp:67
static GameState & global()
进程级全局单例(脚本便利入口)。
eve::Result< void > restoreSnapshotJson(std::string_view json)
Validate and atomically restore a canonical RPG game-state JSON document.
void switchOn(const std::string &name)
Switch on.
Definition GameState.cpp:51
eve::Result< std::string > snapshotJson() const
Serialize this state as the canonical versioned RPG game-state JSON document.
double getSelfVariable(const std::string &scope, const std::string &name) const
Returns the self variable.
Definition GameState.cpp:75
void setSelfString(const std::string &scope, const std::string &name, std::string value)
Scoped string facts (for example a .dnut story cursor JSON blob).
Definition GameState.cpp:88
bool hasSelfVariable(const std::string &scope, const std::string &name) const
True when self variable.
Definition GameState.cpp:82
std::string getSelfString(const std::string &scope, const std::string &name) const
Return a scoped string fact, or an empty string when absent.
Definition GameState.cpp:92
void switchOff(const std::string &name)
Switch off.
Definition GameState.cpp:53
void setVariable(const std::string &name, double value)
设置/读取/增减变量。
Definition GameState.cpp:60
void clear()
清空全部状态。
void setSwitch(const std::string &name, bool on)
设置开关。
Definition GameState.cpp:49
bool hasSelfString(const std::string &scope, const std::string &name) const
Whether a scoped string fact is present.
Definition GameState.cpp:99
void setSelfVariable(const std::string &scope, const std::string &name, double value)
独立变量:scope(如 "map:1:event:3")下按名字存数字。
Definition GameState.cpp:71
bool isSwitchOn(const std::string &name) const
开关是否打开。
Definition GameState.cpp:55
RPG 模块的基础实体:把属性 / 状态 / 技能三张表挂到一个 ECS 实体上。