Chira Engine
A customizable MIT-licensed game engine.
ConEntry.cpp
1 #include "ConEntry.h"
2 
3 #include <algorithm>
4 #include <utility>
5 #include <config/Config.h>
6 
7 using namespace chira;
8 
9 CHIRA_CREATE_LOG(CONENTRY);
10 
11 [[maybe_unused]]
12 ConCommand about{"about", "Prints the description of the given convar(s) or concommand(s).", [](ConCommand::CallbackArgs args) {
13  for (const auto& name : args) {
14  if (ConEntryRegistry::hasConCommand(name)) {
15  LOG_CONENTRY.infoImportant(std::string{*ConEntryRegistry::getConCommand(name)});
16  } else if (ConEntryRegistry::hasConVar(name)) {
17  LOG_CONENTRY.infoImportant(std::string{*ConEntryRegistry::getConVar(name)});
18  } else {
19  LOG_CONENTRY.infoImportant("Unknown console entry \"{}\"", name);
20  }
21  }
22 }};
23 
24 [[maybe_unused]]
25 ConCommand find{"find", "Finds convars and/or concommands from the given substring.", [](ConCommand::CallbackArgs args) {
26  bool resultFound = false;
27  for (const auto& substr : args) {
28  for (const auto& concommand: ConEntryRegistry::getConCommandList()) {
29  if (concommand.find(substr) != std::string::npos) {
30  LOG_CONENTRY.infoImportant(std::string{*ConEntryRegistry::getConCommand(concommand)});
31  resultFound = true;
32  }
33  }
34  for (const auto& convar: ConEntryRegistry::getConVarList()) {
35  if (convar.find(substr) != std::string::npos) {
36  LOG_CONENTRY.infoImportant(std::string{*ConEntryRegistry::getConVar(convar)});
37  resultFound = true;
38  }
39  }
40  }
41  if (!resultFound) {
42  LOG_CONENTRY.infoImportant("No results.");
43  }
44 }};
45 
46 [[maybe_unused]]
47 ConCommand con_entries{"con_entries", "Prints the description of every convar and concommand currently registered.", [] {
48  LOG_CONENTRY.infoImportant("-- Commands --");
49  auto concommandList = ConEntryRegistry::getConCommandList();
50  std::sort(concommandList.begin(), concommandList.end());
51  for (const auto& name : concommandList) {
52  if (const auto* concommand = ConEntryRegistry::getConCommand(name); !concommand->hasFlag(CON_FLAG_HIDDEN)) {
53  LOG_CONENTRY.infoImportant(std::string{*concommand});
54  }
55  }
56 
57  LOG_CONENTRY.infoImportant("-- Variables --");
58  auto convarList = ConEntryRegistry::getConVarList();
59  std::sort(convarList.begin(), convarList.end());
60  for (const auto& name : convarList) {
61  if (const auto* convar = ConEntryRegistry::getConVar(name); !convar->hasFlag(CON_FLAG_HIDDEN)) {
62  LOG_CONENTRY.infoImportant(std::string{*convar});
63  }
64  }
65 }};
66 
67 ConEntry::ConEntry(std::string name_, std::string description_, int flags_)
68  : name(std::move(name_))
69  , description(std::move(description_))
70  , flags(flags_) {}
71 
72 std::string_view ConEntry::getName() const {
73  return this->name;
74 }
75 
76 std::string_view ConEntry::getDescription() const {
77  return this->description;
78 }
79 
80 bool ConEntry::hasFlag(ConFlags flag) const {
81  return this->flags & flag;
82 }
83 
84 ConCommand::ConCommand(std::string name_, const std::function<void()>& callback_, int flags_)
85  : ConCommand(std::move(name_), "No description provided.", callback_, flags_) {}
86 
87 ConCommand::ConCommand(std::string name_, std::function<void(ConCommand::CallbackArgs)> callback_, int flags_)
88  : ConCommand(std::move(name_), "No description provided.", std::move(callback_), flags_) {}
89 
90 ConCommand::ConCommand(std::string name_, std::string description_, const std::function<void()>& callback_, int flags_)
91  : ConCommand(std::move(name_), std::move(description_), [callback_](ConCommand::CallbackArgs) {callback_();}, flags_) {}
92 
93 ConCommand::ConCommand(std::string name_, std::string description_, std::function<void(ConCommand::CallbackArgs)> callback_, int flags_)
94  : ConEntry(std::move(name_), std::move(description_), flags_)
95  , callback(std::move(callback_)) {
96  runtime_assert(ConEntryRegistry::registerConCommand(this), "This ConCommand already exists!");
97 }
98 
99 ConCommand::~ConCommand() {
100  ConEntryRegistry::deregisterConCommand(this);
101 }
102 
103 void ConCommand::fire(ConCommand::CallbackArgs args) {
104  if (this->hasFlag(CON_FLAG_CHEAT) && !ConVar::areCheatsEnabled()) {
105  LOG_CONENTRY.error("Cannot fire cheat-protected ConCommand with cheats disabled.");
106  return;
107  }
108  this->callback(args);
109 }
110 
111 bool ConEntryRegistry::hasConCommand(std::string_view name) {
112  for (const auto* concommand : ConEntryRegistry::getConCommands()) {
113  if (concommand->getName() == name) {
114  return true;
115  }
116  }
117  return false;
118 }
119 
120 ConCommand* ConEntryRegistry::getConCommand(std::string_view name) {
121  for (auto* concommand : ConEntryRegistry::getConCommands()) {
122  if (concommand->getName() == name) {
123  return concommand;
124  }
125  }
126  return nullptr;
127 }
128 
129 std::vector<std::string> ConEntryRegistry::getConCommandList() {
130  std::vector<std::string> out;
131  for (const auto* concommand : ConEntryRegistry::getConCommands()) {
132  out.emplace_back(concommand->getName().data());
133  }
134  return out;
135 }
136 
137 std::vector<ConCommand*>& ConEntryRegistry::getConCommands() {
138  static std::vector<ConCommand*> concommands;
139  return concommands;
140 }
141 
142 bool ConEntryRegistry::registerConCommand(ConCommand* concommand) {
143  if (ConEntryRegistry::hasConCommand(concommand->getName()))
144  return false;
145  ConEntryRegistry::getConCommands().push_back(concommand);
146  return true;
147 }
148 
149 void ConEntryRegistry::deregisterConCommand(ConCommand* concommand) {
150  auto& concommands = ConEntryRegistry::getConCommands();
151  concommands.erase(std::remove_if(concommands.begin(), concommands.end(), [concommand](ConCommand* other) {
152  return concommand->getName() == other->getName();
153  }), concommands.end());
154 }
155 
156 bool ConEntryRegistry::hasConVar(std::string_view name) {
157  for (const auto* convar : ConEntryRegistry::getConVars()) {
158  if (convar->getName() == name) {
159  return true;
160  }
161  }
162  return false;
163 }
164 
165 ConVar* ConEntryRegistry::getConVar(std::string_view name) {
166  for (auto* convar : ConEntryRegistry::getConVars()) {
167  if (convar->getName() == name) {
168  return convar;
169  }
170  }
171  return nullptr;
172 }
173 
174 std::vector<std::string> ConEntryRegistry::getConVarList() {
175  std::vector<std::string> out;
176  for (const auto* convar : ConEntryRegistry::getConVars()) {
177  out.emplace_back(convar->getName().data());
178  }
179  return out;
180 }
181 
182 std::vector<ConVar*>& ConEntryRegistry::getConVars() {
183  static std::vector<ConVar*> convars;
184  return convars;
185 }
186 
187 JSONSettingsLoader& ConEntryRegistry::getConVarCache() {
188  static JSONSettingsLoader convarCache{"convars.json"};
189  return convarCache;
190 }
191 
192 bool ConEntryRegistry::registerConVar(ConVar* convar) {
193  if (ConEntryRegistry::hasConVar(convar->getName()))
194  return false;
195  ConEntryRegistry::getConVars().push_back(convar);
196 
197  if (convar->hasFlag(CON_FLAG_CACHE) && ConEntryRegistry::getConVarCache().hasValue(convar->getName().data())) {
198  // There's an entry for the convar in cache, load it
199  switch (convar->getType()) {
200  using enum ConVarType;
201  case BOOLEAN: {
202  auto value = convar->getValue<bool>();
203  ConEntryRegistry::getConVarCache().getValue(convar->getName().data(), &value);
204  convar->setValue(value, false);
205  break;
206  }
207  case INTEGER: {
208  auto value = convar->getValue<int>();
209  ConEntryRegistry::getConVarCache().getValue(convar->getName().data(), &value);
210  convar->setValue(value, false);
211  break;
212  }
213  case DOUBLE: {
214  auto value = convar->getValue<double>();
215  ConEntryRegistry::getConVarCache().getValue(convar->getName().data(), &value);
216  convar->setValue(value, false);
217  break;
218  }
219  case STRING: {
220  auto value = convar->getValue<std::string>();
221  ConEntryRegistry::getConVarCache().getValue(convar->getName().data(), &value);
222  convar->setValue(value, false);
223  break;
224  }
225  }
226  }
227  return true;
228 }
229 
230 void ConEntryRegistry::deregisterConVar(ConVar* convar) {
231  // Cache it!
232  if (convar->hasFlag(CON_FLAG_CACHE)) {
233  auto& cache = ConEntryRegistry::getConVarCache();
234  switch (convar->getType()) {
235  using enum ConVarType;
236  case BOOLEAN:
237  cache.setValue(convar->getName().data(), convar->getValue<bool>(), true, true);
238  break;
239  case INTEGER:
240  cache.setValue(convar->getName().data(), convar->getValue<int>(), true, true);
241  break;
242  case DOUBLE:
243  cache.setValue(convar->getName().data(), convar->getValue<double>(), true, true);
244  break;
245  case STRING:
246  cache.setValue(convar->getName().data(), convar->getValue<std::string>(), true, true);
247  }
248  }
249 
250  // Erase it!
251  auto& convars = ConEntryRegistry::getConVars();
252  convars.erase(std::remove_if(convars.begin(), convars.end(), [convar](ConVar* other) {
253  return convar->getName() == other->getName();
254  }), convars.end());
255 }
256 
257 ConVar::~ConVar() {
258  ConEntryRegistry::deregisterConVar(this);
259 }
260 
261 ConVarType ConVar::getType() const {
262  return this->type;
263 }
264 
265 std::string_view ConVar::getTypeAsString() const {
266  switch (this->type) {
267  using enum ConVarType;
268  case BOOLEAN:
269  return "boolean";
270  case INTEGER:
271  return "integer";
272  case DOUBLE:
273  return "double";
274  case STRING:
275  return "string";
276  }
277  return "";
278 }
279 
280 ConVar sv_cheats{"sv_cheats", false, "Unlocks certain console entries that break gameplay."};
281 
283  return sv_cheats.getValue<bool>();
284 }
Definition: ConEntry.h:26
static bool areCheatsEnabled()
Convenience function to check the value of sv_cheats.
Definition: ConEntry.cpp:282