12#include "../string_func.h"
13#include "../settings_type.h"
15#include "../script/squirrel.hpp"
20#include "../network/network_content.h"
21#include "../3rdparty/md5/md5.h"
22#include "../tar_type.h"
24#include "../safeguards.h"
31 auto p = this->
main_script.find_last_of(PATHSEPCHAR);
32 this->
main_script.erase(p != std::string::npos ? p + 1 : 0);
39 this->
engine->LoadScript(filename);
41 Debug(script, 0,
"Fatal error '{}' when trying to load the script '{}'.", e.
GetErrorMessage(), filename);
47ScriptScanner::ScriptScanner() =
default;
52 this->
engine->SetGlobalPointer(
this);
56void ScriptScanner::Initialize(std::string_view name)
58 this->
engine = std::make_unique<Squirrel>(name);
56void ScriptScanner::Initialize(std::string_view name) {
…}
65ScriptScanner::~ScriptScanner()
83 this->info_vector.clear();
88 std::string script_original_name = this->
GetScriptName(*info);
89 std::string script_name = fmt::format(
"{}.{}", script_original_name, info->GetVersion());
92 if (info->GetShortName().size() != 4) {
93 Debug(script, 0,
"The script '{}' returned a string from GetShortName() which is not four characters. Unable to load the script.", info->GetName());
103 if (it->second->GetMainScript() == info->GetMainScript()) {
108 Debug(script, 1,
"Registering two scripts with the same name and version");
109 Debug(script, 1,
" 1: {}", it->second->GetMainScript());
110 Debug(script, 1,
" 2: {}", info->GetMainScript());
111 Debug(script, 1,
"The first is taking precedence.");
116 ScriptInfo *script_info = this->info_vector.emplace_back(std::move(info)).get();
117 this->
info_list[script_name] = script_info;
125 }
else if (it->second->GetVersion() < script_info->
GetVersion()) {
126 it->second = script_info;
133 fmt::format_to(output_iterator,
"List of {}:\n", this->
GetScannerName());
135 for (
const auto &item : list) {
139 fmt::format_to(output_iterator,
"\n");
154 bool AddFile(
const std::string &filename,
size_t,
const std::string &)
override
157 uint8_t buffer[1024];
161 auto f =
FioFOpenFile(filename,
"rb", this->dir, &size);
162 if (!f.has_value())
return false;
165 while ((len = fread(buffer, 1, (size >
sizeof(buffer)) ?
sizeof(buffer) : size, *f)) != 0 && size != 0) {
167 checksum.Append(buffer, len);
171 checksum.Finish(tmp_md5sum);
174 this->md5sum ^= tmp_md5sum;
154 bool AddFile(
const std::string &filename,
size_t,
const std::string &)
override {
…}
191 auto str = std::string_view{info.
GetShortName()}.substr(0, 4);
192 for (
size_t j = 0; j < str.size(); j++)
id |=
static_cast<uint8_t
>(str[j]) << (8 * j);
195 if (!md5sum)
return true;
199 TarList::iterator iter;
200 if (!tar_filename.empty() && (iter = _tar_list[dir].find(tar_filename)) != _tar_list[dir].end()) {
203 for (
const auto &tar : _tar_filelist[dir]) {
205 if (tar.second.tar_filename != iter->first)
continue;
208 auto ext = tar.first.rfind(
'.');
209 if (ext == std::string_view::npos || !
StrEqualsIgnoreCase(tar.first.substr(ext),
".nut"))
continue;
211 checksum.
AddFile(tar.first, 0, tar_filename);
219 checksum.
Scan(
".nut", path);
227 for (
const auto &item : this->
info_list) {
228 if (
IsSameScript(ci, md5sum, *item.second, this->GetDirectory()))
return true;
235 for (
const auto &item : this->
info_list) {
236 if (
IsSameScript(ci, md5sum, *item.second, this->GetDirectory()))
return item.second->GetMainScript();
Helper for scanning for files with a given name.
uint Scan(std::string_view extension, Subdirectory sd, bool tars=true, bool recursive=true)
Scan for files with the given extension in the given search path.
Subdirectory subdir
The current sub directory we are searching through.
All static information from an Script like name, version, etc.
const std::string & GetName() const
Get the Name of the script.
const std::string & GetMainScript() const
Get the filename of the main.nut script.
const std::string & GetShortName() const
Get the 4 character long short name of the script.
int GetVersion() const
Get the version of the script.
const std::string & GetTarFile() const
Get the filename of the tar the script is in.
const std::string & GetDescription() const
Get the description of the script.
virtual bool IsDeveloperOnly() const
Can this script be selected by developers only?
bool AddFile(const std::string &filename, size_t basepath_length, const std::string &tar_filename) override
Add a file with the given filename.
virtual std::string_view GetScannerName() const =0
Get the type of the script, in plural.
std::string tar_file
If, which tar file the script was in.
virtual void RegisterAPI(class Squirrel &engine)=0
Register the API for this ScriptInfo.
void Reset()
Reset all allocated lists.
virtual std::string GetScriptName(ScriptInfo &info)=0
Get the script name how to store the script in memory.
void RescanDir()
Rescan the script dir.
virtual Subdirectory GetDirectory() const =0
Get the directory to scan in.
std::string main_script
The full path of the script.
void GetConsoleList(std::back_insert_iterator< std::string > &output_iterator, bool newest_only) const
Get the list of registered scripts to print on the console.
std::optional< std::string_view > FindMainScript(const ContentInfo &ci, bool md5sum)
Find a script of a ContentInfo.
virtual std::string_view GetFileName() const =0
Get the filename to scan for this type of script.
ScriptInfoList info_list
The list of all script.
ScriptInfoList info_single_list
The list of all unique script. The best script (highest version) is shown.
void RegisterScript(std::unique_ptr< class ScriptInfo > &&info)
Register a ScriptInfo to the scanner.
std::unique_ptr< class Squirrel > engine
The engine we're scanning with.
bool HasScript(const struct ContentInfo &ci, bool md5sum)
Check whether we have a script with the exact characteristics as ci.
void ResetEngine()
Reset the engine to ensure a clean environment for further steps.
A throw-class that is given when the script made a fatal error.
const std::string & GetErrorMessage() const
The error message associated with the fatal error.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
std::optional< FileHandle > FioFOpenFile(std::string_view filename, std::string_view mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
bool FioCheckFileExists(std::string_view filename, Subdirectory subdir)
Check whether the given file exists.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
The definition of Script_FatalError.
ScriptInfo keeps track of all information of a script, like Author, Description, ....
static bool IsSameScript(const ContentInfo &ci, bool md5sum, const ScriptInfo &info, Subdirectory dir)
Check whether the script given in info is the same as in ci based on the shortname and md5 sum.
Declarations of the class for the script scanner.
std::map< std::string, class ScriptInfo *, CaseInsensitiveComparator > ScriptInfoList
Type for the list of scripts.
ClientSettings _settings_client
The current settings for this game.
bool StrEqualsIgnoreCase(std::string_view str1, std::string_view str2)
Compares two string( view)s for equality, while ignoring the case of the characters.
GUISettings gui
settings related to the GUI
Container for all important information about a piece of content.
uint32_t unique_id
Unique ID; either GRF ID or shortname.
MD5Hash md5sum
The MD5 checksum.
bool ai_developer_tools
activate AI/GS developer tools
Helper for creating a MD5sum of all files within of a script.
MD5Hash md5sum
The final md5sum.
bool AddFile(const std::string &filename, size_t, const std::string &) override
Add a file with the given filename.
Subdirectory dir
The directory to look in.
ScriptFileChecksumCreator(Subdirectory dir)
Initialise the md5sum to be all zeroes, so we can easily xor the data.