24 lua_(lua), localizer_(loc), event_emitter_(emitter), root_(r), virtual_root_(vr) {}
26void addon_registry::load_addon_toc_(
27 const std::string& addon_name,
const std::string& addon_directory) {
28 auto& addons = addon_list_[addon_directory];
29 if (addons.find(addon_name) != addons.end())
35 a.
directory = addon_directory +
"/" + addon_name;
37 std::string toc_file = a.
directory +
"/" + addon_name +
".toc";
38 std::ifstream file(toc_file);
43 while (std::getline(file, line)) {
44 utils::replace(line,
"\r",
"");
48 std::string_view line_view = line;
50 if (line_view.size() >= 2 && line_view[0] ==
'#' && line_view[1] ==
'#') {
51 line_view = line_view.substr(2);
52 line_view = utils::trim(line_view,
' ');
53 auto args = utils::cut_first(line_view,
":");
54 if (!args.first.empty() && !args.second.empty()) {
55 std::string_view key = utils::trim(args.first,
' ');
56 std::string_view value = utils::trim(args.second,
' ');
58 if (key ==
"Interface") {
65 <<
"Wrong UI version for \"" << addon_name
67 <<
", expected: " << lxgui_ui_version <<
"). AddOn disabled."
71 }
else if (key ==
"Title")
73 else if (key ==
"Version")
75 else if (key ==
"Author")
77 else if (key ==
"SavedVariables") {
78 for (
auto var : utils::cut(value,
",")) {
79 var = utils::trim(var,
' ');
80 if (!utils::has_no_content(var))
86 line_view = utils::trim(line_view,
' ');
87 if (!utils::has_no_content(line_view))
96 addons[addon_name] = a;
99void addon_registry::load_addon_files_(
const addon& a) {
103 for (
const auto& file : a.file_list) {
105 if (extension ==
".lua") {
106 auto result = lua_.do_file(file);
107 if (!result.valid()) {
108 std::string err = result.get<sol::error>().what();
110 event_emitter_.
fire_event(
"LUA_ERROR", {err});
113 this->parse_layout_file_(file, a);
117 std::string saved_variables_file =
118 "saves/interface/" + a.main_directory +
"/" + a.name +
".lua";
121 auto result = lua_.do_file(saved_variables_file);
122 if (!result.valid()) {
123 std::string err = result.get<sol::error>().what();
125 event_emitter_.
fire_event(
"LUA_ERROR", {err});
129 event_emitter_.
fire_event(
"ADDON_LOADED", {a.name});
134 this->load_addon_toc_(sub_dir, directory);
136 std::vector<addon*> core_addon_stack;
137 std::vector<addon*> addon_stack;
140 auto& addons = addon_list_[directory];
142 std::ifstream file(directory +
"/addons.txt");
143 if (file.is_open()) {
145 while (std::getline(file, line)) {
146 utils::replace(line,
"\r",
"");
150 std::string_view line_view = line;
152 if (line_view[0] ==
'#') {
153 line_view = line_view.substr(1);
154 line_view = utils::trim(line_view,
' ');
155 core = line_view ==
"Core";
157 auto args = utils::cut_first(line_view,
":");
158 if (!args.first.empty() && !args.second.empty()) {
159 std::string_view key = utils::trim(args.first,
' ');
160 std::string_view value = utils::trim(args.second,
' ');
161 auto iter = addons.find(std::string{key});
162 if (iter != addons.end()) {
164 core_addon_stack.push_back(&iter->second);
166 addon_stack.push_back(&iter->second);
168 iter->second.enabled = value ==
"1";
176 for (
auto* a : core_addon_stack) {
178 this->load_addon_files_(*a);
181 for (
auto* a : addon_stack) {
183 this->load_addon_files_(*a);
186 current_addon_ =
nullptr;
189std::string
serialize(
const std::string& tab,
const sol::object& value)
noexcept {
190 if (value.is<
double>()) {
191 return utils::to_string(value.as<
double>());
192 }
else if (value.is<
int>()) {
193 return utils::to_string(value.as<
int>());
194 }
else if (value.is<std::string>()) {
195 return "\"" + utils::to_string(value.as<std::string>()) +
"\"";
196 }
else if (value.is<sol::table>()) {
201 sol::table table = value.as<sol::table>();
202 for (
const auto& key_value : table) {
203 content += tab +
" [" +
serialize(
"", key_value.first) +
204 "] = " +
serialize(tab +
" ", key_value.second) +
",\n";
207 if (!content.empty())
208 result +=
"\n" + content + tab;
218 sol::object value = lua.globals()[variable];
223 for (
const auto& directory : addon_list_) {
229void addon_registry::save_variables_(
const addon& a)
const noexcept {
230 if (!a.saved_variable_list.empty()) {
233 <<
"gui::addon_registry: unable to create directory 'saves/interface/"
234 << a.main_directory <<
"'" << std::endl;
238 std::ofstream file(
"saves/interface/" + a.main_directory +
"/" + a.name +
".lua");
239 for (
const auto& variable : a.saved_variable_list) {
241 if (!serialized.empty())
242 file << serialized <<
"\n";
248 return current_addon_;