Prepare scripting environment
This commit is contained in:
parent
e78dcdf21b
commit
508cc5d51e
@ -13,13 +13,61 @@ namespace game
|
|||||||
|
|
||||||
MSG_ReadData_t MSG_ReadData;
|
MSG_ReadData_t MSG_ReadData;
|
||||||
|
|
||||||
|
RemoveRefToValue_t RemoveRefToValue;
|
||||||
|
|
||||||
Sys_ShowConsole_t Sys_ShowConsole;
|
Sys_ShowConsole_t Sys_ShowConsole;
|
||||||
|
|
||||||
|
VM_Notify_t VM_Notify;
|
||||||
|
|
||||||
int* cmd_args;
|
int* cmd_args;
|
||||||
int* cmd_argc;
|
int* cmd_argc;
|
||||||
const char*** cmd_argv;
|
const char*** cmd_argv;
|
||||||
}
|
|
||||||
|
|
||||||
|
short* scrVarGlob;
|
||||||
|
char** scrMemTreePub;
|
||||||
|
|
||||||
|
void AddRefToValue(VariableValue* value)
|
||||||
|
{
|
||||||
|
if (value->type == SCRIPT_OBJECT)
|
||||||
|
{
|
||||||
|
++scrVarGlob[4 * value->u.entityId];
|
||||||
|
}
|
||||||
|
else if (value->type == SCRIPT_STRING)
|
||||||
|
{
|
||||||
|
static const auto size = is_sp() ? 16 : 12;
|
||||||
|
const auto ref_count = reinterpret_cast<unsigned volatile *>(*scrMemTreePub + size * value
|
||||||
|
->u.stringValue);
|
||||||
|
InterlockedIncrement(ref_count);
|
||||||
|
}
|
||||||
|
else if (value->type == SCRIPT_VECTOR)
|
||||||
|
{
|
||||||
|
if (!*PBYTE(value->u.vectorValue - 1))
|
||||||
|
{
|
||||||
|
++*PWORD(value->u.vectorValue - 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scr_entref_t Scr_GetEntityIdRef(const unsigned int id)
|
||||||
|
{
|
||||||
|
static auto class_array = reinterpret_cast<DWORD*>(SELECT_VALUE(0x19AFC84, 0x1E72184, 0x1D3C804));
|
||||||
|
static auto ent_array = reinterpret_cast<WORD*>(SELECT_VALUE(0x19AFC82, 0x1E72182, 0x1D3C802));
|
||||||
|
|
||||||
|
scr_entref_t result{};
|
||||||
|
result.raw.classnum = static_cast<unsigned short>(class_array[2 * id]) >> 8;
|
||||||
|
result.raw.entnum = ent_array[4 * id];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* SL_ConvertToString(unsigned int stringValue)
|
||||||
|
{
|
||||||
|
if (!stringValue) return nullptr;
|
||||||
|
|
||||||
|
static const auto size = is_sp() ? 16 : 12;
|
||||||
|
return *scrMemTreePub + size * stringValue + 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
launcher::mode mode = launcher::mode::none;
|
launcher::mode mode = launcher::mode::none;
|
||||||
|
|
||||||
@ -50,10 +98,17 @@ namespace game
|
|||||||
|
|
||||||
native::MSG_ReadData = native::MSG_ReadData_t(SELECT_VALUE(0, 0x5592A0, 0));
|
native::MSG_ReadData = native::MSG_ReadData_t(SELECT_VALUE(0, 0x5592A0, 0));
|
||||||
|
|
||||||
|
native::RemoveRefToValue = native::RemoveRefToValue_t(SELECT_VALUE(0x477EA0, 0x565730, 0x4E8A40));
|
||||||
|
|
||||||
native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
|
native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
|
||||||
|
|
||||||
|
native::VM_Notify = native::VM_Notify_t(SELECT_VALUE(0x610200, 0x569720, 0x4EF450));
|
||||||
|
|
||||||
native::cmd_args = reinterpret_cast<int*>(SELECT_VALUE(0x1750750, 0x1C978D0, 0x1B455F8));
|
native::cmd_args = reinterpret_cast<int*>(SELECT_VALUE(0x1750750, 0x1C978D0, 0x1B455F8));
|
||||||
native::cmd_argc = reinterpret_cast<int*>(SELECT_VALUE(0x1750794, 0x1C97914, 0x1B4563C));
|
native::cmd_argc = reinterpret_cast<int*>(SELECT_VALUE(0x1750794, 0x1C97914, 0x1B4563C));
|
||||||
native::cmd_argv = reinterpret_cast<const char***>(SELECT_VALUE(0x17507B4, 0x1C97934, 0x1B4565C));
|
native::cmd_argv = reinterpret_cast<const char***>(SELECT_VALUE(0x17507B4, 0x1C97934, 0x1B4565C));
|
||||||
|
|
||||||
|
native::scrVarGlob = reinterpret_cast<short*>(SELECT_VALUE(0x19AFC80, 0x1E72180, 0x1D3C800));
|
||||||
|
native::scrMemTreePub = reinterpret_cast<char**>(SELECT_VALUE(0x196FB00, 0x1E32000, 0x1C152A4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,15 +18,30 @@ namespace game
|
|||||||
typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync);
|
typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync);
|
||||||
extern DB_LoadXAssets_t DB_LoadXAssets;
|
extern DB_LoadXAssets_t DB_LoadXAssets;
|
||||||
|
|
||||||
typedef void(*MSG_ReadData_t)(msg_t *msg, void *data, int len);
|
typedef void (*MSG_ReadData_t)(msg_t* msg, void* data, int len);
|
||||||
extern MSG_ReadData_t MSG_ReadData;
|
extern MSG_ReadData_t MSG_ReadData;
|
||||||
|
|
||||||
|
typedef void (*RemoveRefToValue_t)(scriptType_e type, VariableUnion u);
|
||||||
|
extern RemoveRefToValue_t RemoveRefToValue;
|
||||||
|
|
||||||
typedef void (*Sys_ShowConsole_t)();
|
typedef void (*Sys_ShowConsole_t)();
|
||||||
extern Sys_ShowConsole_t Sys_ShowConsole;
|
extern Sys_ShowConsole_t Sys_ShowConsole;
|
||||||
|
|
||||||
|
typedef void (*VM_Notify_t)(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top);
|
||||||
|
extern VM_Notify_t VM_Notify;
|
||||||
|
|
||||||
extern int* cmd_args;
|
extern int* cmd_args;
|
||||||
extern int* cmd_argc;
|
extern int* cmd_argc;
|
||||||
extern const char*** cmd_argv;
|
extern const char*** cmd_argv;
|
||||||
|
|
||||||
|
extern short* scrVarGlob;
|
||||||
|
extern char** scrMemTreePub;
|
||||||
|
|
||||||
|
void AddRefToValue(VariableValue* value);
|
||||||
|
|
||||||
|
scr_entref_t Scr_GetEntityIdRef(unsigned int id);
|
||||||
|
|
||||||
|
const char* SL_ConvertToString(unsigned int stringValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_mp();
|
bool is_mp();
|
||||||
|
@ -399,5 +399,56 @@ namespace game
|
|||||||
int allocFlags;
|
int allocFlags;
|
||||||
int freeFlags;
|
int freeFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct scr_entref_raw
|
||||||
|
{
|
||||||
|
unsigned __int16 entnum;
|
||||||
|
unsigned __int16 classnum;
|
||||||
|
};
|
||||||
|
|
||||||
|
union scr_entref_t
|
||||||
|
{
|
||||||
|
unsigned int val;
|
||||||
|
scr_entref_raw raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum scriptType_e
|
||||||
|
{
|
||||||
|
SCRIPT_NONE = 0,
|
||||||
|
SCRIPT_OBJECT = 1,
|
||||||
|
SCRIPT_STRING = 2,
|
||||||
|
SCRIPT_VECTOR = 4,
|
||||||
|
SCRIPT_FLOAT = 5,
|
||||||
|
SCRIPT_INTEGER = 6,
|
||||||
|
SCRIPT_END = 8, // Custom
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VariableStackBuffer
|
||||||
|
{
|
||||||
|
const char* pos;
|
||||||
|
unsigned __int16 size;
|
||||||
|
unsigned __int16 bufLen;
|
||||||
|
unsigned __int16 localId;
|
||||||
|
char time;
|
||||||
|
char buf[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
union VariableUnion
|
||||||
|
{
|
||||||
|
int intValue;
|
||||||
|
float floatValue;
|
||||||
|
unsigned int stringValue;
|
||||||
|
const float* vectorValue;
|
||||||
|
const char* codePosValue;
|
||||||
|
unsigned int pointerValue;
|
||||||
|
VariableStackBuffer* stackValue;
|
||||||
|
unsigned int entityId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VariableValue
|
||||||
|
{
|
||||||
|
VariableUnion u;
|
||||||
|
scriptType_e type;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
src/module/notification.cpp
Normal file
37
src/module/notification.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/module_loader.hpp"
|
||||||
|
#include "notification.hpp"
|
||||||
|
#include "utils/hook.hpp"
|
||||||
|
|
||||||
|
void notification::post_load()
|
||||||
|
{
|
||||||
|
utils::hook(SELECT_VALUE(0x6109F3, 0x56B637, 0x4EDFF7), vm_notify_stub, HOOK_CALL).install()->quick();
|
||||||
|
utils::hook(SELECT_VALUE(0x6128BE, 0x56D541, 0x4EFAF9), vm_notify_stub, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
|
if (game::is_sp())
|
||||||
|
{
|
||||||
|
utils::hook(0x610970, vm_notify_stub, HOOK_JUMP).install()->quick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void notification::vm_notify_stub(const unsigned int notify_id, const unsigned short type,
|
||||||
|
game::native::VariableValue* stack)
|
||||||
|
{
|
||||||
|
event e;
|
||||||
|
e.name = game::native::SL_ConvertToString(type);
|
||||||
|
e.entity = game::native::Scr_GetEntityIdRef(notify_id);
|
||||||
|
|
||||||
|
for (auto value = stack; value->type != game::native::SCRIPT_END; --value)
|
||||||
|
{
|
||||||
|
e.arguments.emplace_back(*value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!e.arguments.empty())
|
||||||
|
{
|
||||||
|
printf("");
|
||||||
|
}
|
||||||
|
|
||||||
|
game::native::VM_Notify(notify_id, type, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_MODULE(notification)
|
20
src/module/notification.hpp
Normal file
20
src/module/notification.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "loader/module_loader.hpp"
|
||||||
|
#include "scripting.hpp"
|
||||||
|
|
||||||
|
class notification final : public module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class event final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string name;
|
||||||
|
game::native::scr_entref_t entity;
|
||||||
|
std::vector<scripting::variable> arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
void post_load() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void vm_notify_stub(unsigned int notify_id, unsigned short type, game::native::VariableValue* stack);
|
||||||
|
};
|
@ -1,26 +1,101 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "loader/module_loader.hpp"
|
#include "scripting.hpp"
|
||||||
#include "game/game.hpp"
|
|
||||||
|
|
||||||
class scripting final : public module
|
utils::hook scripting::start_hook_;
|
||||||
|
utils::hook scripting::stop_hook_;
|
||||||
|
|
||||||
|
std::mutex scripting::mutex_;
|
||||||
|
std::vector<std::function<void()>> scripting::start_callbacks_;
|
||||||
|
std::vector<std::function<void()>> scripting::stop_callbacks_;
|
||||||
|
|
||||||
|
scripting::variable::variable(game::native::VariableValue value) : value_(value)
|
||||||
{
|
{
|
||||||
public:
|
game::native::AddRefToValue(&value);
|
||||||
void post_load() override
|
}
|
||||||
|
|
||||||
|
scripting::variable::~variable()
|
||||||
|
{
|
||||||
|
game::native::RemoveRefToValue(this->value_.type, this->value_.u);
|
||||||
|
}
|
||||||
|
|
||||||
|
scripting::variable::operator game::native::VariableValue() const
|
||||||
|
{
|
||||||
|
return this->value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scripting::post_load()
|
||||||
|
{
|
||||||
|
start_hook_.initialize(SELECT_VALUE(0x50C575, 0x50D4F2, 0x48A026), []()
|
||||||
{
|
{
|
||||||
this->chai_.add(chaiscript::fun(&function), "function");
|
start_execution();
|
||||||
|
static_cast<void(*)()>(start_hook_.get_original())();
|
||||||
double d = this->chai_.eval<double>("function(3, 4.75);");
|
}, HOOK_CALL)->install()->quick();
|
||||||
printf("Result: %f", d);
|
|
||||||
|
stop_hook_.initialize(SELECT_VALUE(0x528B04, 0x569E46, 0x4F03FA), []()
|
||||||
|
{
|
||||||
|
stop_execution();
|
||||||
|
static_cast<void(*)()>(stop_hook_.get_original())();
|
||||||
|
}, HOOK_CALL)->install()->quick();
|
||||||
|
|
||||||
|
on_start([this]()
|
||||||
|
{
|
||||||
|
this->chai_ = std::make_unique<chaiscript::ChaiScript>();
|
||||||
|
});
|
||||||
|
|
||||||
|
on_stop([this]()
|
||||||
|
{
|
||||||
|
this->chai_ = {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void scripting::pre_destroy()
|
||||||
|
{
|
||||||
|
this->chai_ = {};
|
||||||
|
start_callbacks_.clear();
|
||||||
|
stop_callbacks_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void scripting::on_start(const std::function<void()>& callback)
|
||||||
|
{
|
||||||
|
std::lock_guard _(mutex_);
|
||||||
|
start_callbacks_.push_back(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scripting::on_stop(const std::function<void()>& callback)
|
||||||
|
{
|
||||||
|
std::lock_guard _(mutex_);
|
||||||
|
stop_callbacks_.push_back(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scripting::start_execution()
|
||||||
|
{
|
||||||
|
std::vector<std::function<void()>> copy;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard _(mutex_);
|
||||||
|
copy = start_callbacks_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
for (const auto& callback : copy)
|
||||||
chaiscript::ChaiScript chai_;
|
{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static double function(int i, double j)
|
void scripting::stop_execution()
|
||||||
{
|
{
|
||||||
return i * j;
|
std::vector<std::function<void()>> copy;
|
||||||
}
|
|
||||||
|
{
|
||||||
|
std::lock_guard _(mutex_);
|
||||||
|
copy = stop_callbacks_;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& callback : copy)
|
||||||
|
{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
REGISTER_MODULE(scripting)
|
REGISTER_MODULE(scripting)
|
||||||
|
39
src/module/scripting.hpp
Normal file
39
src/module/scripting.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "loader/module_loader.hpp"
|
||||||
|
#include "game/game.hpp"
|
||||||
|
#include "utils/hook.hpp"
|
||||||
|
|
||||||
|
class scripting final : public module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class variable final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
variable(game::native::VariableValue value);
|
||||||
|
~variable();
|
||||||
|
|
||||||
|
operator game::native::VariableValue() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
game::native::VariableValue value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void post_load() override;
|
||||||
|
void pre_destroy() override;
|
||||||
|
|
||||||
|
static void on_start(const std::function<void()>& callback);
|
||||||
|
static void on_stop(const std::function<void()>& callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<chaiscript::ChaiScript> chai_;
|
||||||
|
|
||||||
|
static utils::hook start_hook_;
|
||||||
|
static utils::hook stop_hook_;
|
||||||
|
|
||||||
|
static std::mutex mutex_;
|
||||||
|
static std::vector<std::function<void()>> start_callbacks_;
|
||||||
|
static std::vector<std::function<void()>> stop_callbacks_;
|
||||||
|
|
||||||
|
static void start_execution();
|
||||||
|
static void stop_execution();
|
||||||
|
};
|
@ -156,6 +156,11 @@ namespace utils
|
|||||||
return this->place_;
|
return this->place_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* hook::get_original() const
|
||||||
|
{
|
||||||
|
return this->original_;
|
||||||
|
}
|
||||||
|
|
||||||
void hook::nop(void* place, const size_t length)
|
void hook::nop(void* place, const size_t length)
|
||||||
{
|
{
|
||||||
DWORD old_protect;
|
DWORD old_protect;
|
||||||
|
@ -80,6 +80,7 @@ namespace utils
|
|||||||
hook* uninstall(bool unprotect = true);
|
hook* uninstall(bool unprotect = true);
|
||||||
|
|
||||||
void* get_address() const;
|
void* get_address() const;
|
||||||
|
void* get_original() const;
|
||||||
void quick();
|
void quick();
|
||||||
|
|
||||||
static bool iat(nt::module module, const std::string& target_module, const std::string& process, void* stub);
|
static bool iat(nt::module module, const std::string& target_module, const std::string& process, void* stub);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user