Merge pull request #330 from diamante0018/script-loading
[Script] (feature request): Enchance script loading
This commit is contained in:
commit
5c5b9f0d5a
@ -3,16 +3,19 @@
|
||||
namespace Components
|
||||
{
|
||||
std::string Script::ScriptName;
|
||||
std::vector<int> Script::ScriptHandles;
|
||||
std::unordered_map<std::string, Game::BuiltinFunctionDef> Script::CustomScrFunctions;
|
||||
std::unordered_map<std::string, Game::BuiltinMethodDef> Script::CustomScrMethods;
|
||||
std::vector<std::string> Script::ScriptNameStack;
|
||||
unsigned short Script::FunctionName;
|
||||
std::unordered_map<std::string, std::string> Script::ScriptStorage;
|
||||
std::unordered_map<int, std::string> Script::ScriptBaseProgramNum;
|
||||
int Script::LastFrameTime = -1;
|
||||
|
||||
std::unordered_map<const char*, const char*> Script::ReplacedFunctions;
|
||||
const char* Script::ReplacedPos = nullptr;
|
||||
int Script::LastFrameTime = -1;
|
||||
|
||||
std::vector<int> Script::ScriptMainHandles;
|
||||
std::vector<int> Script::ScriptInitHandles;
|
||||
|
||||
void Script::FunctionError()
|
||||
{
|
||||
@ -201,68 +204,70 @@ namespace Components
|
||||
Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\n{}\n{}\n(see console for actual details)\n", msgbuf, Script::ScriptName);
|
||||
}
|
||||
|
||||
int Script::LoadScriptAndLabel(const std::string& script, const std::string& label)
|
||||
void Script::Scr_LoadGameType_Stub()
|
||||
{
|
||||
Logger::Print("Loading script {}.gsc...\n", script);
|
||||
|
||||
if (!Game::Scr_LoadScript(script.data()))
|
||||
for (const auto& handle : Script::ScriptMainHandles)
|
||||
{
|
||||
Logger::Print("Script {} encountered an error while loading. (doesn't exist?)", script);
|
||||
Logger::Error(Game::ERR_DROP, "Could not find script '{}'", script);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Print("Script {}.gsc loaded successfully.\n", script);
|
||||
}
|
||||
|
||||
Logger::Debug("Finding script handle {}::{}...", script.data(), label.data());
|
||||
const auto handle = Game::Scr_GetFunctionHandle(script.data(), label.data());
|
||||
if (handle)
|
||||
{
|
||||
Logger::Print("Script handle {}::{} loaded successfully.\n", script, label);
|
||||
return handle;
|
||||
}
|
||||
|
||||
Logger::Print("Script handle {}::{} couldn't be loaded. (file with no entry point?)\n", script, label);
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Script::LoadGameType()
|
||||
{
|
||||
for (const auto& handle : Script::ScriptHandles)
|
||||
{
|
||||
Game::Scr_FreeThread(Game::Scr_ExecThread(handle, 0));
|
||||
const auto id = Game::Scr_ExecThread(handle, 0);
|
||||
Game::Scr_FreeThread(static_cast<std::uint16_t>(id));
|
||||
}
|
||||
|
||||
Game::Scr_LoadGameType();
|
||||
}
|
||||
|
||||
void Script::LoadGameTypeScript()
|
||||
void Script::Scr_StartupGameType_Stub()
|
||||
{
|
||||
Script::ScriptHandles.clear();
|
||||
for (const auto& handle : Script::ScriptInitHandles)
|
||||
{
|
||||
const auto id = Game::Scr_ExecThread(handle, 0);
|
||||
Game::Scr_FreeThread(static_cast<std::uint16_t>(id));
|
||||
}
|
||||
|
||||
Game::Scr_StartupGameType();
|
||||
}
|
||||
|
||||
void Script::GScr_LoadGameTypeScript_Stub()
|
||||
{
|
||||
// Clear handles (from previous GSC loading session)
|
||||
Script::ScriptMainHandles.clear();
|
||||
Script::ScriptInitHandles.clear();
|
||||
|
||||
const auto list = FileSystem::GetFileList("scripts/", "gsc");
|
||||
|
||||
for (auto file : list)
|
||||
for (const auto& file : list)
|
||||
{
|
||||
file.insert(0, "scripts/");
|
||||
std::string script = "scripts/" + file;
|
||||
|
||||
if (Utils::String::EndsWith(file, ".gsc"))
|
||||
if (Utils::String::EndsWith(script, ".gsc"))
|
||||
{
|
||||
file = file.substr(0, file.size() - 4);
|
||||
script = script.substr(0, script.size() - 4);
|
||||
}
|
||||
|
||||
auto handle = Script::LoadScriptAndLabel(file, "init");
|
||||
Logger::Print("Loading script {}.gsc...\n", script);
|
||||
|
||||
if (handle)
|
||||
if (!Game::Scr_LoadScript(script.data()))
|
||||
{
|
||||
Script::ScriptHandles.push_back(handle);
|
||||
Logger::Print("Script {} encountered an error while loading. (doesn't exist?)", script);
|
||||
Logger::Error(Game::ERR_DROP, "Could not find script '{}'", script);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
Logger::Print("Script {}.gsc loaded successfully.\n", script);
|
||||
Logger::Debug("Finding script handle main or init...");
|
||||
|
||||
const auto initHandle = Game::Scr_GetFunctionHandle(script.data(), "init");
|
||||
if (initHandle != 0)
|
||||
{
|
||||
handle = Script::LoadScriptAndLabel(file, "main");
|
||||
if (handle) Script::ScriptHandles.push_back(handle);
|
||||
Script::ScriptInitHandles.push_back(initHandle);
|
||||
}
|
||||
|
||||
const auto mainHandle = Game::Scr_GetFunctionHandle(script.data(), "main");
|
||||
if (mainHandle != 0)
|
||||
{
|
||||
Script::ScriptMainHandles.push_back(mainHandle);
|
||||
}
|
||||
|
||||
// Allow scripts with no handles
|
||||
}
|
||||
|
||||
Game::GScr_LoadGameTypeScript();
|
||||
@ -687,8 +692,9 @@ namespace Components
|
||||
Utils::Hook(0x612EA2, Script::FunctionError, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x434260, Script::CompileError, HOOK_JUMP).install()->quick();
|
||||
|
||||
Utils::Hook(0x48EFFE, Script::LoadGameType, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x45D44A, Script::LoadGameTypeScript, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x48EFFE, Script::Scr_LoadGameType_Stub, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x48F008, Script::Scr_StartupGameType_Stub, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x45D44A, Script::GScr_LoadGameTypeScript_Stub, HOOK_CALL).install()->quick();
|
||||
|
||||
// Fetch custom functions
|
||||
Utils::Hook(0x44E72E, Script::BuiltIn_GetFunctionStub, HOOK_CALL).install()->quick(); // Scr_GetFunction
|
||||
|
@ -8,8 +8,6 @@ namespace Components
|
||||
public:
|
||||
Script();
|
||||
|
||||
static int LoadScriptAndLabel(const std::string& script, const std::string& label);
|
||||
|
||||
static void AddFunction(const char* name, Game::BuiltinFunction func, int type = 0);
|
||||
static void AddMethod(const char* name, Game::BuiltinMethod func, int type = 0);
|
||||
|
||||
@ -19,16 +17,19 @@ namespace Components
|
||||
|
||||
private:
|
||||
static std::string ScriptName;
|
||||
static std::vector<int> ScriptHandles;
|
||||
static std::unordered_map<std::string, Game::BuiltinFunctionDef> CustomScrFunctions;
|
||||
static std::unordered_map<std::string, Game::BuiltinMethodDef> CustomScrMethods;
|
||||
static std::vector<std::string> ScriptNameStack;
|
||||
static unsigned short FunctionName;
|
||||
static std::unordered_map<std::string, std::string> ScriptStorage;
|
||||
static std::unordered_map<int, std::string> ScriptBaseProgramNum;
|
||||
static int LastFrameTime;
|
||||
|
||||
static std::vector<int> ScriptMainHandles;
|
||||
static std::vector<int> ScriptInitHandles;
|
||||
|
||||
static std::unordered_map<const char*, const char*> ReplacedFunctions;
|
||||
static const char* ReplacedPos;
|
||||
static int LastFrameTime;
|
||||
|
||||
static void CompileError(unsigned int offset, const char* message, ...);
|
||||
static void PrintSourcePos(const char* filename, unsigned int offset);
|
||||
@ -43,8 +44,9 @@ namespace Components
|
||||
static void RestoreScriptName();
|
||||
static void RestoreScriptNameStub();
|
||||
|
||||
static void LoadGameType();
|
||||
static void LoadGameTypeScript();
|
||||
static void Scr_LoadGameType_Stub();
|
||||
static void Scr_StartupGameType_Stub();
|
||||
static void GScr_LoadGameTypeScript_Stub();
|
||||
|
||||
static Game::BuiltinFunction BuiltIn_GetFunctionStub(const char** pName, int* type);
|
||||
static Game::BuiltinMethod BuiltIn_GetMethod(const char** pName, int* type);
|
||||
|
@ -274,6 +274,7 @@ namespace Game
|
||||
RemoveRefToObject_t RemoveRefToObject = RemoveRefToObject_t(0x437190);
|
||||
|
||||
Scr_LoadGameType_t Scr_LoadGameType = Scr_LoadGameType_t(0x4D9520);
|
||||
Scr_StartupGameType_t Scr_StartupGameType = Scr_StartupGameType_t(0x438720);
|
||||
|
||||
Scr_LoadScript_t Scr_LoadScript = Scr_LoadScript_t(0x45D940);
|
||||
Scr_GetFunctionHandle_t Scr_GetFunctionHandle = Scr_GetFunctionHandle_t(0x4234F0);
|
||||
|
@ -717,9 +717,12 @@ namespace Game
|
||||
typedef void(__cdecl * Scr_ShutdownAllocNode_t)();
|
||||
extern Scr_ShutdownAllocNode_t Scr_ShutdownAllocNode;
|
||||
|
||||
typedef int(__cdecl * Scr_LoadGameType_t)();
|
||||
typedef void(__cdecl * Scr_LoadGameType_t)();
|
||||
extern Scr_LoadGameType_t Scr_LoadGameType;
|
||||
|
||||
typedef void(__cdecl * Scr_StartupGameType_t)();
|
||||
extern Scr_StartupGameType_t Scr_StartupGameType;
|
||||
|
||||
typedef int(__cdecl * Scr_LoadScript_t)(const char*);
|
||||
extern Scr_LoadScript_t Scr_LoadScript;
|
||||
|
||||
@ -750,13 +753,13 @@ namespace Game
|
||||
typedef int(__cdecl * Scr_GetFunctionHandle_t)(const char* filename, const char* name);
|
||||
extern Scr_GetFunctionHandle_t Scr_GetFunctionHandle;
|
||||
|
||||
typedef int(__cdecl * Scr_ExecThread_t)(int, int);
|
||||
typedef int(__cdecl * Scr_ExecThread_t)(int handle, unsigned int paramcount);
|
||||
extern Scr_ExecThread_t Scr_ExecThread;
|
||||
|
||||
typedef int(__cdecl * Scr_ExecEntThread_t)(gentity_s* ent, int handle, unsigned int paramcount);
|
||||
extern Scr_ExecEntThread_t Scr_ExecEntThread;
|
||||
|
||||
typedef int(__cdecl * Scr_FreeThread_t)(int);
|
||||
typedef void(__cdecl * Scr_FreeThread_t)(unsigned __int16 handle);
|
||||
extern Scr_FreeThread_t Scr_FreeThread;
|
||||
|
||||
typedef void(__cdecl * Scr_Notify_t)(gentity_t *ent, unsigned __int16 stringValue, unsigned int paramcount);
|
||||
|
Loading…
Reference in New Issue
Block a user