Skip to content

Commit

Permalink
Inheriting compatibility mode from parent script. Deducing compatibil…
Browse files Browse the repository at this point in the history
…ity mode from script file extension. (#32)
  • Loading branch information
MiranDMC authored Nov 12, 2023
1 parent 26d93da commit a03ca23
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 22 deletions.
6 changes: 3 additions & 3 deletions source/CCustomOpcodeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1457,7 +1457,7 @@ namespace CLEO
auto filename = reinterpret_cast<CCustomScript*>(thread)->ResolvePath(path, DIR_CLEO); // legacy: default search location is game\cleo directory
TRACE("[0A92] Starting new custom script %s from thread named %s", filename.c_str(), thread->GetName().c_str());

auto cs = new CCustomScript(filename.c_str());
auto cs = new CCustomScript(filename.c_str(), false, thread);
SetScriptCondResult(thread, cs && cs->IsOK());
if (cs && cs->IsOK())
{
Expand Down Expand Up @@ -1498,7 +1498,7 @@ namespace CLEO
filename += ".cm"; // add custom mission extension
TRACE("[0A94] Starting new custom mission %s from thread named %s", filename.c_str(), thread->GetName().c_str());

auto cs = new CCustomScript(filename.c_str(), true);
auto cs = new CCustomScript(filename.c_str(), true, thread);
SetScriptCondResult(thread, cs && cs->IsOK());
if (cs && cs->IsOK())
{
Expand Down Expand Up @@ -3415,7 +3415,7 @@ extern "C"
}

// if "label == 0" then "script_name" need to be the file name
auto cs = new CCustomScript(script_name, false, reinterpret_cast<CCustomScript*>(fromThread), label);
auto cs = new CCustomScript(script_name, false, fromThread, label);
if (fromThread) SetScriptCondResult(fromThread, cs && cs->IsOK());
if (cs && cs->IsOK())
{
Expand Down
80 changes: 62 additions & 18 deletions source/CScriptEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,7 @@ namespace CLEO
}

// TODO: Consider split into 2 classes: CCustomExternalScript, CCustomChildScript
CCustomScript::CCustomScript(const char *szFileName, bool bIsMiss, CCustomScript *parent, int label)
CCustomScript::CCustomScript(const char *szFileName, bool bIsMiss, CRunningScript *parent, int label)
: CRunningScript(), bSaveEnabled(false), bOK(false),
LastSearchPed(0), LastSearchCar(0), LastSearchObj(0),
CompatVer(CLEO_VER_CUR)
Expand All @@ -1318,10 +1318,39 @@ namespace CLEO
// store script file directory and name
FS::path path = szFileName;
path = FS::weakly_canonical(path);

// deduce compatibility mode from filetype extension
if (path.extension() == cs4_ext)
CompatVer = CLEO_VER_4;
else
if (path.extension() == cs3_ext)
CompatVer = CLEO_VER_3;

if(CompatVer == CLEO_VER_CUR && parent != nullptr && parent-IsCustom())
{
// inherit compatibility mode from parent
CompatVer = ((CCustomScript*)parent)->GetCompatibility();

// try loading file with same compatibility mode filetype extension
auto compatPath = path;
if(CompatVer == CLEO_VER_4)
{
compatPath.replace_extension(cs4_ext);
if(FS::is_regular_file(compatPath))
path = compatPath;
}
else
if (CompatVer == CLEO_VER_3)
{
compatPath.replace_extension(cs3_ext);
if (FS::is_regular_file(compatPath))
path = compatPath;
}
}

scriptFileDir = path.parent_path().string();
scriptFileName = path.filename().string();

workDir = Filepath_Root;
workDir = Filepath_Root; // game root

try
{
Expand All @@ -1331,17 +1360,22 @@ namespace CLEO
if (!parent)
throw std::logic_error("Trying to create external thread from label without parent thread");

BaseIP = parent->GetBasePointer();
CurrentIP = parent->GetBasePointer() - label;
memcpy(Name, parent->Name, sizeof(Name));
dwChecksum = parent->dwChecksum;
parentThread = parent;
parent->childThreads.push_back(this);
if (!parent->IsCustom())
throw std::logic_error("Only custom threads can spawn children threads from label");

auto cs = (CCustomScript*)parent;

BaseIP = cs->GetBasePointer();
CurrentIP = cs->GetBasePointer() - label;
memcpy(Name, cs->Name, sizeof(Name));
dwChecksum = cs->dwChecksum;
parentThread = cs;
cs->childThreads.push_back(this);
}
else
{
using std::ios;
std::ifstream is(szFileName, std::ios::binary);
std::ifstream is(path.string().c_str(), std::ios::binary);
is.exceptions(std::ios::badbit | std::ios::failbit);
std::size_t length;
is.seekg(0, std::ios::end);
Expand All @@ -1360,23 +1394,33 @@ namespace CLEO
}
is.read(reinterpret_cast<char *>(BaseIP), length);

auto fname = strrchr(szFileName, '\\') + 1;
if (!fname) fname = strrchr(szFileName, '/') + 1;
if (fname < szFileName) fname = szFileName;
memcpy(Name, fname, sizeof(Name));
Name[7] = '\0';
dwChecksum = crc32(reinterpret_cast<BYTE *>(BaseIP), length);
dwChecksum = crc32(reinterpret_cast<BYTE*>(BaseIP), length);

// thread name from filename
auto threadNamePath = path;
if(threadNamePath.extension() == cs3_ext || threadNamePath.extension() == cs4_ext)
{
threadNamePath.replace_extension(cs_ext); // keep original extension even in compatibility modes
}
auto fName = threadNamePath.filename().string();

memset(Name, '\0', sizeof(Name));
if(!fName.empty())
{
auto len = min(fName.length(), sizeof(Name) - 1); // and text terminator
memcpy(Name, fName.c_str(), len);
}
}
lastScriptCreated = this;
bOK = true;
}
catch (std::exception& e)
{
LOG_WARNING(0, "Error during loading of custom script %s occured.\nError message: %s", szFileName, e.what());
LOG_WARNING(0, "Error during loading of custom script %s occured.\nError message: %s", path.string().c_str(), e.what());
}
catch (...)
{
LOG_WARNING(0, "Unknown error during loading of custom script %s occured.", szFileName);
LOG_WARNING(0, "Unknown error during loading of custom script %s occured.", path.string().c_str());
}
}

Expand Down
2 changes: 1 addition & 1 deletion source/CScriptEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ namespace CLEO
inline DWORD& GetLastSearchPed() { return LastSearchPed; }
inline DWORD& GetLastSearchVehicle() { return LastSearchCar; }
inline DWORD& GetLastSearchObject() { return LastSearchObj; }
CCustomScript(const char *szFileName, bool bIsMiss = false, CCustomScript *parent = nullptr, int label = 0);
CCustomScript(const char *szFileName, bool bIsMiss = false, CRunningScript *parent = nullptr, int label = 0);
~CCustomScript();

void Process();
Expand Down

0 comments on commit a03ca23

Please sign in to comment.