4 #include <Strings/components/logger/logger.h>
5 #include <Strings/components/utils/io/io.h>
6 #include <Strings/components/utils/string/string.h>
7 #include <Strings/components/utils/list/list.h>
8 #include <Strings/components/3rdparty/rapidxml/rapidxml.hpp>
9 #include <Strings/components/classes/map/map.h>
10 #include <Strings/components/utils/converters/converters.h>
11 #include <HEKGuerilla/components/projects/projects.h>
13 #include "../ToolCommand.hpp"
14 #include "../console.h"
17 #ifdef TOOL_LIB_EXPORTS
18 #define TOOL_LIB_API __declspec(dllexport)
20 #define TOOL_LIB_API __declspec(dllimport)
30 bool parse_debug =
false;
32 std::vector<std::string> PreprocessArgs(std::vector<std::string> args)
34 std::vector<std::string> processed_args = std::vector<std::string>();
36 for (
int i = 0; i < args.size(); i++)
38 if (args[i] ==
"-parse-debug")
44 processed_args.push_back(args[i]);
48 return processed_args;
54 command =
"parse-scripts";
55 syntax =
"parse-scripts [project filename] [-parse-debug]";
56 description =
"preprocess scripts, ensures that scripts can be referenced by the game engine and editing kit";
59 int execute(std::vector<std::string> args)
61 args = PreprocessArgs(args);
64 std::string project_filename = BlamStrings::Utils::IO::GetFileNameWithoutExtension(project_root) +
".blam";
68 project_filename = args[0];
71 BlamProject* project_info = Guerilla::Projects::LoadProject(project_root + project_filename);
73 if (!project_info->IsLoaded())
75 BlamStrings::Logger::LogEvent(
"failed to create stub project: could not load project info (tried to "
76 "read from file path: " + project_root + project_filename +
")", WSV_ERROR);
80 BlamStrings::Logger::LogEvent(
"project path was assumed from directory path - if your .blam file "
81 "has a different name, use " + syntax +
" to specify the filename", WSV_WARNING);
88 std::vector<std::string> sources = GetSourceFilesFromVcx(project_info->GetVcxprojPath());
89 std::vector<std::string> sources_raw = GetSourceFilesFromVcx(project_info->GetVcxprojPath(),
true);
90 std::vector<std::string> script_names = std::vector<std::string>();
92 for (std::string file_path : sources)
94 std::string file_contents = BlamStrings::Utils::IO::GetFileContentsAsString(file_path);
95 BlamStrings::Logger::LogEvent(
"analyzing '" + file_path +
"'...");
97 while (str_contains(file_contents,
"/*",
true))
99 int start = file_contents.find(
"/*");
101 if (start == std::string::npos)
106 int end = file_contents.find(
"*/", start);
108 if (end == std::string::npos)
113 file_contents = file_contents.erase(start, end - start);
116 file_contents = str_replace(file_contents,
"public",
"");
117 file_contents = str_replace(file_contents,
"protected",
"");
118 file_contents = str_replace(file_contents,
"private",
"");
119 file_contents = str_replace(file_contents,
"class",
"class:");
120 file_contents = str_replace(file_contents,
" ",
"");
121 file_contents = str_replace(file_contents,
"\r",
"");
122 file_contents = str_replace(file_contents,
"\n",
"");
123 file_contents = str_replace(file_contents,
"\t",
"");
127 BlamStrings::Utils::IO::CreateNewFile(file_path +
".PARSED", file_contents);
133 int pos = file_contents.find(
"BSCRIPTclass:", offset);
135 if (pos == std::string::npos)
140 pos = pos +
sizeof(
"BSCRIPTclass:") - 1;
142 int end_pos = pos + 1;
143 bool is_script =
false;
145 while (end_pos != std::string::npos && end_pos < file_contents.length())
147 if (file_contents.at(end_pos) ==
':')
158 std::string script_name = file_contents.substr(pos, end_pos - pos);
160 if (!BlamStrings::Utils::List::Contains(script_names, script_name))
162 script_names.push_back(script_name);
172 std::string db_contents =
"";
174 for (std::string script_name : script_names)
176 db_contents += script_name +
"\n";
179 BlamStrings::Utils::IO::CreateNewFile(project_root +
"/_build/scripts.db", db_contents);
184 std::string template_file = BlamStrings::Utils::IO::GetFileContentsAsString(
"./content/blam/default_stub_project/gamescripts.cpp.template");
186 std::string includes =
"";
187 std::string creation_functions =
"";
188 std::string registry_lines =
"";
190 for (std::string source_file : sources_raw)
192 if (!source_file.ends_with(
".h"))
197 includes +=
"#include <" + source_file +
">\n";
200 for (std::string script_name : script_names)
202 std::string function_name =
"__blam_create_script__" + script_name;
203 creation_functions += script_name +
"* " + function_name +
"() { return new " + script_name +
"(); }\n";
204 registry_lines +=
" BlamAPI::Scripts::RegisterScriptType(\"" + script_name +
"\", &" + function_name +
");\n";
207 template_file = str_replace(template_file,
"%%FUNCTIONS%%", creation_functions);
208 template_file = str_replace(template_file,
"%%REGISTRATIONS%%", registry_lines);
209 template_file = str_replace(template_file,
"%%INCLUDES%%", includes);
211 BlamStrings::Utils::IO::CreateNewFile(project_root +
"_build/_internal/game/gamescripts.cpp", template_file);
214 BlamStrings::Logger::LogEvent(
"finished");
222 std::vector<std::string> files = std::vector<std::string>();
223 std::string vcxproj_dir = BlamStrings::Utils::IO::GetContainingFolder(vcxproj_path);
225 char* data =
nullptr;
226 int64_t data_size = 0;
228 if (!BlamStrings::Utils::IO::ReadFile(vcxproj_path, (
void**)&data, &data_size))
230 BlamStrings::Logger::LogEvent(
"cannot load vcxproj: ReadFile() returned false", WSV_WARNING);
234 rapidxml::xml_document<char>* document =
new rapidxml::xml_document();
235 document->parse<0>(data);
237 rapidxml::xml_node<>* root = document->first_node();
239 for (rapidxml::xml_node<>* node = root->first_node(); node; node = node->next_sibling())
241 if (str_tolower(node->name()) !=
"itemgroup")
246 for (rapidxml::xml_node<>* child_node = node->first_node(); child_node; child_node = child_node->next_sibling())
248 if (str_tolower(child_node->name()) ==
"clinclude" || str_tolower(child_node->name()) ==
"clcompile")
250 if (preserve_relative_paths)
252 files.push_back(child_node->first_attribute(
"Include")->value());
256 files.push_back(BlamStrings::Utils::IO::NormalizePath(vcxproj_dir +
"/"
257 + child_node->first_attribute(
"Include")->value()));