Add notification support

This commit is contained in:
momo5502 2019-01-19 00:57:19 +01:00
parent e3d47528f6
commit a1f1f99a45
4 changed files with 194 additions and 10 deletions

View File

@ -15,8 +15,12 @@ namespace game
MSG_ReadData_t MSG_ReadData; MSG_ReadData_t MSG_ReadData;
MT_AllocIndex_t MT_AllocIndex;
RemoveRefToValue_t RemoveRefToValue; RemoveRefToValue_t RemoveRefToValue;
Scr_NotifyId_t Scr_NotifyId;
SL_GetStringOfSize_t SL_GetStringOfSize; SL_GetStringOfSize_t SL_GetStringOfSize;
Sys_ShowConsole_t Sys_ShowConsole; Sys_ShowConsole_t Sys_ShowConsole;
@ -29,6 +33,7 @@ namespace game
short* scrVarGlob; short* scrVarGlob;
char** scrMemTreePub; char** scrMemTreePub;
char* scrMemTreeGlob;
unsigned int* scr_numParam; unsigned int* scr_numParam;
unsigned int* scr_numArgs; unsigned int* scr_numArgs;
@ -65,6 +70,24 @@ namespace game
} }
} }
void* MT_Alloc(const int numBytes, const int type)
{
return scrMemTreeGlob + 12 * size_t(MT_AllocIndex(numBytes, type));
}
const float* Scr_AllocVector(const float *v)
{
const auto mem = static_cast<DWORD*>(MT_Alloc(16, 2));
*mem = 0;
const auto array = reinterpret_cast<float*>(mem + 1);
array[0] = v[0];
array[1] = v[1];
array[2] = v[2];
return array;
}
void Scr_ClearOutParams() void Scr_ClearOutParams()
{ {
const auto num_params = *scr_numParam; const auto num_params = *scr_numParam;
@ -109,7 +132,7 @@ namespace game
return *scrMemTreePub + size * stringValue + 4; return *scrMemTreePub + size * stringValue + 4;
} }
unsigned int SL_GetString(const char *str, const unsigned int user) unsigned int SL_GetString(const char* str, const unsigned int user)
{ {
return SL_GetStringOfSize(str, user, strlen(str) + 1, 7); return SL_GetStringOfSize(str, user, strlen(str) + 1, 7);
} }
@ -146,8 +169,12 @@ 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::MT_AllocIndex = native::MT_AllocIndex_t(SELECT_VALUE(0x4B9610, 0x562080, 0x4E6C30));
native::RemoveRefToValue = native::RemoveRefToValue_t(SELECT_VALUE(0x477EA0, 0x565730, 0x4E8A40)); native::RemoveRefToValue = native::RemoveRefToValue_t(SELECT_VALUE(0x477EA0, 0x565730, 0x4E8A40));
native::Scr_NotifyId = native::Scr_NotifyId_t(SELECT_VALUE(0x610980, 0x56B5E0, 0x4EFAA0));
native::SL_GetStringOfSize = native::SL_GetStringOfSize_t(SELECT_VALUE(0x4E13F0, 0x564650, 0x4E7490)); native::SL_GetStringOfSize = native::SL_GetStringOfSize_t(SELECT_VALUE(0x4E13F0, 0x564650, 0x4E7490));
native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0)); native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
@ -160,14 +187,20 @@ namespace game
native::scrVarGlob = reinterpret_cast<short*>(SELECT_VALUE(0x19AFC80, 0x1E72180, 0x1D3C800)); native::scrVarGlob = reinterpret_cast<short*>(SELECT_VALUE(0x19AFC80, 0x1E72180, 0x1D3C800));
native::scrMemTreePub = reinterpret_cast<char**>(SELECT_VALUE(0x196FB00, 0x1E32000, 0x1C152A4)); native::scrMemTreePub = reinterpret_cast<char**>(SELECT_VALUE(0x196FB00, 0x1E32000, 0x1C152A4));
native::scrMemTreeGlob = reinterpret_cast<char*>(SELECT_VALUE(0x186DA00, 0x1D6FF00, 0x1C16600));
native::scr_numParam = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BF2598, 0x20B4A98, 0x1F5B098)); native::scr_numParam = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BF2598, 0x20B4A98, 0x1F5B098));
native::scr_numArgs = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BF2594, 0x20B4A94, 0x1F5B094)); native::scr_numArgs = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BF2594, 0x20B4A94, 0x1F5B094));
native::scr_stackPtr = reinterpret_cast<native::VariableValue**>(SELECT_VALUE(0x1BF2590, 0x20B4A90, 0x1F5B090)); native::scr_stackPtr = reinterpret_cast<native::VariableValue**>(SELECT_VALUE(0x1BF2590, 0x20B4A90, 0x1F5B090));
native::scr_stackEndPtr = reinterpret_cast<native::VariableValue**>(SELECT_VALUE(0x1BF2584, 0x20B4A84, 0x1F5B084)); native::scr_stackEndPtr = reinterpret_cast<native::VariableValue**>( SELECT_VALUE(0x1BF2584, 0x20B4A84,
0x1F5B084
));
native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x184CDB0, 0x1D4F258, 0x1BF59C8)); native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x184CDB0, 0x1D4F258,
native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x186C68C, 0x1D6EB34, 0x1C152A4)); 0x1BF59C8));
native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x186C68C, 0x1D6EB34,
0x1C152A4
));
native::g_script_error_level = reinterpret_cast<int*>(SELECT_VALUE(0x1BEFCFC, 0x20B21FC, 0x1F5B058)); native::g_script_error_level = reinterpret_cast<int*>(SELECT_VALUE(0x1BEFCFC, 0x20B21FC, 0x1F5B058));
native::g_script_error = reinterpret_cast<jmp_buf*>(SELECT_VALUE(0x1BF1D18, 0x20B4218, 0x1F5A818)); native::g_script_error = reinterpret_cast<jmp_buf*>(SELECT_VALUE(0x1BF1D18, 0x20B4218, 0x1F5A818));

View File

@ -12,7 +12,7 @@ namespace game
typedef void (*Cmd_AddCommand_t)(const char* cmdName, void (*function)(), cmd_function_t* allocedCmd); typedef void (*Cmd_AddCommand_t)(const char* cmdName, void (*function)(), cmd_function_t* allocedCmd);
extern Cmd_AddCommand_t Cmd_AddCommand; extern Cmd_AddCommand_t Cmd_AddCommand;
typedef void (*Com_Error_t)(int code, const char *fmt, ...); typedef void (*Com_Error_t)(int code, const char* fmt, ...);
extern Com_Error_t Com_Error; extern Com_Error_t Com_Error;
typedef void (*Conbuf_AppendText_t)(const char* message); typedef void (*Conbuf_AppendText_t)(const char* message);
@ -24,10 +24,16 @@ namespace game
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* (*MT_AllocIndex_t)(int numBytes, int type);
extern MT_AllocIndex_t MT_AllocIndex;
typedef void (*RemoveRefToValue_t)(scriptType_e type, VariableUnion u); typedef void (*RemoveRefToValue_t)(scriptType_e type, VariableUnion u);
extern RemoveRefToValue_t RemoveRefToValue; extern RemoveRefToValue_t RemoveRefToValue;
typedef unsigned int (*SL_GetStringOfSize_t)(const char *str, unsigned int user, unsigned int len, int type); typedef void (*Scr_NotifyId_t)(unsigned int id, unsigned int stringValue, unsigned int paramcount);
extern Scr_NotifyId_t Scr_NotifyId;
typedef unsigned int (*SL_GetStringOfSize_t)(const char* str, unsigned int user, unsigned int len, int type);
extern SL_GetStringOfSize_t SL_GetStringOfSize; extern SL_GetStringOfSize_t SL_GetStringOfSize;
typedef void (*Sys_ShowConsole_t)(); typedef void (*Sys_ShowConsole_t)();
@ -42,6 +48,7 @@ namespace game
extern short* scrVarGlob; extern short* scrVarGlob;
extern char** scrMemTreePub; extern char** scrMemTreePub;
extern char* scrMemTreeGlob;
extern unsigned int* scr_numParam; extern unsigned int* scr_numParam;
extern unsigned int* scr_numArgs; extern unsigned int* scr_numArgs;
@ -58,12 +65,15 @@ namespace game
void AddRefToValue(VariableValue* value); void AddRefToValue(VariableValue* value);
void* MT_Alloc(int numBytes, int type);
const float* Scr_AllocVector(const float* v);
void Scr_ClearOutParams(); void Scr_ClearOutParams();
scr_entref_t Scr_GetEntityIdRef(unsigned int id); scr_entref_t Scr_GetEntityIdRef(unsigned int id);
scr_call_t Scr_GetFunc(unsigned int index); scr_call_t Scr_GetFunc(unsigned int index);
const char* SL_ConvertToString(unsigned int stringValue); const char* SL_ConvertToString(unsigned int stringValue);
unsigned int SL_GetString(const char *str, unsigned int user); unsigned int SL_GetString(const char* str, unsigned int user);
} }
bool is_mp(); bool is_mp();

View File

@ -70,6 +70,11 @@ chaiscript::Boxed_Value scripting::entity::call(const std::string& function,
return this->environment_->call(function, this->get_entity_id(), arguments); return this->environment_->call(function, this->get_entity_id(), arguments);
} }
void scripting::entity::notify(const std::string& event, const std::vector<chaiscript::Boxed_Value>& arguments) const
{
this->environment_->notify(event, this->get_entity_id(), arguments);
}
scripting::variable::variable(game::native::VariableValue value) : value_(value) scripting::variable::variable(game::native::VariableValue value) : value_(value)
{ {
game::native::AddRefToValue(&value); game::native::AddRefToValue(&value);
@ -187,12 +192,71 @@ void scripting::initialize_entity()
this->chai_->add(chaiscript::user_type<entity>(), "entity"); this->chai_->add(chaiscript::user_type<entity>(), "entity");
this->chai_->add(chaiscript::constructor<entity()>(), "entity"); this->chai_->add(chaiscript::constructor<entity()>(), "entity");
this->chai_->add(chaiscript::constructor<entity(const entity&)>(), "entity"); this->chai_->add(chaiscript::constructor<entity(const entity&)>(), "entity");
this->chai_->add(chaiscript::fun(&entity::on_notify), "onNotify"); this->chai_->add(chaiscript::fun(&entity::on_notify), "onNotify");
this->chai_->add(chaiscript::fun([](const entity& ent, const std::string& event,
const std::function<void(const std::vector<chaiscript::Boxed_Value>&)>&
callback)
{
return ent.on_notify(event, callback, false);
}), "onNotify");
this->chai_->add(chaiscript::fun([](entity& lhs, const entity& rhs) -> entity& this->chai_->add(chaiscript::fun([](entity& lhs, const entity& rhs) -> entity&
{ {
return lhs = rhs; return lhs = rhs;
}), "="); }), "=");
this->chai_->add(chaiscript::fun(&entity::notify), "vectorNotify");
this->chai_->add(chaiscript::fun([](const entity& ent, const std::string& event)
{
return ent.notify(event, {});
}), "notify");
this->chai_->add(chaiscript::fun(
[](const entity& ent, const std::string& event,
const chaiscript::Boxed_Value& a1)
{
return ent.notify(event, {a1});
}), "notify");
this->chai_->add(chaiscript::fun(
[](const entity& ent, const std::string& event,
const chaiscript::Boxed_Value& a1,
const chaiscript::Boxed_Value& a2)
{
return ent.notify(event, {a1, a2});
}), "notify");
this->chai_->add(chaiscript::fun(
[](const entity& ent, const std::string& event,
const chaiscript::Boxed_Value& a1,
const chaiscript::Boxed_Value& a2,
const chaiscript::Boxed_Value& a3)
{
return ent.notify(event, {a1, a2, a3});
}), "notify");
this->chai_->add(chaiscript::fun(
[](const entity& ent, const std::string& event,
const chaiscript::Boxed_Value& a1,
const chaiscript::Boxed_Value& a2,
const chaiscript::Boxed_Value& a3,
const chaiscript::Boxed_Value& a4)
{
return ent.notify(event, {a1, a2, a3, a4});
}), "notify");
this->chai_->add(chaiscript::fun(
[](const entity& ent, const std::string& event,
const chaiscript::Boxed_Value& a1,
const chaiscript::Boxed_Value& a2,
const chaiscript::Boxed_Value& a3,
const chaiscript::Boxed_Value& a4,
const chaiscript::Boxed_Value& a5)
{
return ent.notify(event, {a1, a2, a3, a4, a5});
}), "notify");
this->chai_->add(chaiscript::fun(&entity::call), "vectorCall"); this->chai_->add(chaiscript::fun(&entity::call), "vectorCall");
this->chai_->add(chaiscript::fun([](const entity& ent, const std::string& function) this->chai_->add(chaiscript::fun([](const entity& ent, const std::string& function)
{ {
@ -284,6 +348,15 @@ chaiscript::Boxed_Value scripting::make_boxed(const game::native::VariableValue
{ {
return chaiscript::var(entity(this, value.u.entityId)); return chaiscript::var(entity(this, value.u.entityId));
} }
else if (value.type == game::native::SCRIPT_VECTOR)
{
std::vector<float> values;
values.push_back(value.u.vectorValue[0]);
values.push_back(value.u.vectorValue[1]);
values.push_back(value.u.vectorValue[2]);
return chaiscript::var(values);
}
return {}; return {};
} }
@ -338,6 +411,39 @@ void scripting::stop_execution()
} }
} }
void scripting::notify(const std::string& event, const unsigned int entity_id,
std::vector<chaiscript::Boxed_Value> arguments)
{
const auto old_args = *game::native::scr_numArgs;
const auto old_params = *game::native::scr_numParam;
const auto old_stack_ptr = *game::native::scr_stackPtr;
const auto old_stack_end_ptr = *game::native::scr_stackEndPtr;
game::native::VariableValue stack[512];
*game::native::scr_stackPtr = stack;
*game::native::scr_stackEndPtr = &stack[ARRAYSIZE(stack) - 1];
*game::native::scr_numArgs = 0;
*game::native::scr_numParam = 0;
const auto cleanup = gsl::finally([=]()
{
game::native::Scr_ClearOutParams();
*game::native::scr_numArgs = old_args;
*game::native::scr_numParam = old_params;
*game::native::scr_stackPtr = old_stack_ptr;
*game::native::scr_stackEndPtr = old_stack_end_ptr;
});
std::reverse(arguments.begin(), arguments.end());
for (const auto& argument : arguments)
{
this->push_param(argument);
}
const auto event_id = game::native::SL_GetString(event.data(), 0);
game::native::Scr_NotifyId(entity_id, event_id, *game::native::scr_numArgs);
}
chaiscript::Boxed_Value scripting::call(const std::string& function, const unsigned int entity_id, chaiscript::Boxed_Value scripting::call(const std::string& function, const unsigned int entity_id,
std::vector<chaiscript::Boxed_Value> arguments) std::vector<chaiscript::Boxed_Value> arguments)
{ {
@ -379,9 +485,6 @@ chaiscript::Boxed_Value scripting::call(const std::string& function, const unsig
this->push_param(argument); this->push_param(argument);
} }
*game::native::scr_numParam = *game::native::scr_numArgs;
*game::native::scr_numArgs = 0;
if (!call_safe(function_ptr, entity)) if (!call_safe(function_ptr, entity))
{ {
throw std::runtime_error("Error executing function '" + function + "'"); throw std::runtime_error("Error executing function '" + function + "'");
@ -477,6 +580,41 @@ void scripting::push_param(const chaiscript::Boxed_Value& value) const
value_ptr->type = game::native::SCRIPT_STRING; value_ptr->type = game::native::SCRIPT_STRING;
value_ptr->u.stringValue = game::native::SL_GetString(real_value.data(), 0); value_ptr->u.stringValue = game::native::SL_GetString(real_value.data(), 0);
} }
else if (value.get_type_info() == typeid(std::vector<chaiscript::Boxed_Value>))
{
float values[3];
const auto real_value = this->chai_->boxed_cast<std::vector<chaiscript::Boxed_Value>>(value);
if (real_value.size() != 3)
{
throw std::runtime_error("Invalid vector length. Size must be exactly 3");
}
const auto unbox_float = [&real_value, this](size_t index) -> float
{
const auto value = real_value[index];
if (value.get_type_info() == typeid(float))
{
return this->chai_->boxed_cast<float>(value);
}
else if (value.get_type_info() == typeid(double))
{
return float(this->chai_->boxed_cast<double>(value));
}
else if (value.get_type_info() == typeid(int))
{
return float(this->chai_->boxed_cast<int>(value));
}
throw std::runtime_error("Vector element at index " + std::to_string(index) + " is not a number");
};
values[0] = unbox_float(0);
values[1] = unbox_float(1);
values[2] = unbox_float(2);
value_ptr->type = game::native::SCRIPT_VECTOR;
value_ptr->u.vectorValue = game::native::Scr_AllocVector(values);
}
else else
{ {
throw std::runtime_error("Unable to unbox value of type '" + value.get_type_info().bare_name() + "'"); throw std::runtime_error("Unable to unbox value of type '" + value.get_type_info().bare_name() + "'");

View File

@ -23,6 +23,7 @@ public:
game::native::scr_entref_t get_entity_reference() const; game::native::scr_entref_t get_entity_reference() const;
chaiscript::Boxed_Value call(const std::string& function, const std::vector<chaiscript::Boxed_Value>& arguments) const; chaiscript::Boxed_Value call(const std::string& function, const std::vector<chaiscript::Boxed_Value>& arguments) const;
void notify(const std::string& event, const std::vector<chaiscript::Boxed_Value>& arguments) const;
private: private:
scripting* environment_; scripting* environment_;
@ -81,6 +82,8 @@ private:
static void start_execution(); static void start_execution();
static void stop_execution(); static void stop_execution();
void notify(const std::string& event, unsigned int entity_id, std::vector<chaiscript::Boxed_Value> arguments);
void push_param(const chaiscript::Boxed_Value& value) const; void push_param(const chaiscript::Boxed_Value& value) const;
chaiscript::Boxed_Value get_return_value(); chaiscript::Boxed_Value get_return_value();
chaiscript::Boxed_Value call(const std::string& function, unsigned int entity_id, std::vector<chaiscript::Boxed_Value> arguments); chaiscript::Boxed_Value call(const std::string& function, unsigned int entity_id, std::vector<chaiscript::Boxed_Value> arguments);