mirror of
https://github.com/fedddddd/iw5-gsc-utils.git
synced 2025-04-21 05:15:44 +00:00
Add addCommand function
This commit is contained in:
parent
4185224323
commit
ee109d622a
104
src/component/command.cpp
Normal file
104
src/component/command.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include <stdinc.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "game/scripting/entity.hpp"
|
||||||
|
#include "game/scripting/execution.hpp"
|
||||||
|
#include "command.hpp"
|
||||||
|
|
||||||
|
namespace command
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
||||||
|
|
||||||
|
void main_handler()
|
||||||
|
{
|
||||||
|
params params = {};
|
||||||
|
|
||||||
|
const auto command = utils::string::to_lower(params[0]);
|
||||||
|
if (handlers.find(command) != handlers.end())
|
||||||
|
{
|
||||||
|
handlers[command](params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
params::params()
|
||||||
|
: nesting_(game::cmd_args->nesting)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int params::size() const
|
||||||
|
{
|
||||||
|
return game::cmd_args->argc[this->nesting_];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* params::get(const int index) const
|
||||||
|
{
|
||||||
|
if (index >= this->size())
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return game::cmd_args->argv[this->nesting_][index];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string params::join(const int index) const
|
||||||
|
{
|
||||||
|
std::string result = {};
|
||||||
|
|
||||||
|
for (auto i = index; i < this->size(); i++)
|
||||||
|
{
|
||||||
|
if (i > index) result.append(" ");
|
||||||
|
result.append(this->get(i));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_raw(const char* name, void (*callback)())
|
||||||
|
{
|
||||||
|
game::Cmd_AddCommandInternal(name, callback, utils::memory::get_allocator()->allocate<game::cmd_function_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(const char* name, const std::function<void(const params&)>& callback)
|
||||||
|
{
|
||||||
|
const auto command = utils::string::to_lower(name);
|
||||||
|
|
||||||
|
if (handlers.find(command) == handlers.end())
|
||||||
|
{
|
||||||
|
add_raw(name, main_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
handlers[command] = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> script_commands;
|
||||||
|
utils::memory::allocator allocator;
|
||||||
|
|
||||||
|
void add_script_command(const std::string& name, const std::function<void(const params&)>& callback)
|
||||||
|
{
|
||||||
|
script_commands.push_back(name);
|
||||||
|
const auto _name = allocator.duplicate_string(name);
|
||||||
|
add(_name, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_script_commands()
|
||||||
|
{
|
||||||
|
for (const auto& name : script_commands)
|
||||||
|
{
|
||||||
|
handlers.erase(name);
|
||||||
|
game::Cmd_RemoveCommand(name.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
allocator.clear();
|
||||||
|
script_commands.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(command::component)
|
28
src/component/command.hpp
Normal file
28
src/component/command.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace command
|
||||||
|
{
|
||||||
|
class params
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
params();
|
||||||
|
|
||||||
|
int size() const;
|
||||||
|
const char* get(int index) const;
|
||||||
|
std::string join(int index) const;
|
||||||
|
|
||||||
|
const char* operator[](const int index) const
|
||||||
|
{
|
||||||
|
return this->get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int nesting_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void add_raw(const char* name, void (*callback)());
|
||||||
|
void add(const char* name, const std::function<void(const params&)>& callback);
|
||||||
|
|
||||||
|
void add_script_command(const std::string& name, const std::function<void(const params&)>& callback);
|
||||||
|
void clear_script_commands();
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
#include "scripting.hpp"
|
#include "scripting.hpp"
|
||||||
|
#include "command.hpp"
|
||||||
|
|
||||||
#include "game/scripting/event.hpp"
|
#include "game/scripting/event.hpp"
|
||||||
#include "game/scripting/execution.hpp"
|
#include "game/scripting/execution.hpp"
|
||||||
@ -250,6 +251,33 @@ namespace gsc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int make_array()
|
||||||
|
{
|
||||||
|
unsigned int index = 0;
|
||||||
|
const auto variable = game::AllocVariable(&index);
|
||||||
|
variable->w.type = game::SCRIPT_ARRAY;
|
||||||
|
variable->u.f.prev = 0;
|
||||||
|
variable->u.f.next = 0;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_array_key_value(unsigned int parent_id, const std::string& _key, const scripting::script_value& value)
|
||||||
|
{
|
||||||
|
const auto key = game::SL_GetString(_key.data(), 0);
|
||||||
|
|
||||||
|
scripting::push_value(scripting::entity(parent_id));
|
||||||
|
scripting::push_value(value);
|
||||||
|
game::Scr_AddArrayStringIndexed(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_array_value(unsigned int parent_id, const scripting::script_value& value)
|
||||||
|
{
|
||||||
|
scripting::push_value(scripting::entity(parent_id));
|
||||||
|
scripting::push_value(value);
|
||||||
|
game::Scr_AddArray();
|
||||||
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -276,6 +304,32 @@ namespace gsc
|
|||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function::add("addcommand", [](function_args args) -> scripting::script_value
|
||||||
|
{
|
||||||
|
const auto name = args[0].as<std::string>();
|
||||||
|
const auto function = args[1].get_raw();
|
||||||
|
|
||||||
|
if (function.type != game::SCRIPT_FUNCTION)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid type");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto pos = function.u.codePosValue;
|
||||||
|
command::add_script_command(name, [pos](const command::params& params)
|
||||||
|
{
|
||||||
|
const auto array = make_array();
|
||||||
|
for (auto i = 0; i < params.size(); i++)
|
||||||
|
{
|
||||||
|
add_array_value(array, params[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto entity = scripting::entity(array);
|
||||||
|
scripting::exec_ent_thread(*game::levelEntityId, pos, {entity});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
|
||||||
utils::hook::jump(0x56C8EB, call_builtin_stub);
|
utils::hook::jump(0x56C8EB, call_builtin_stub);
|
||||||
utils::hook::jump(0x56CBDC, call_builtin_method_stub);
|
utils::hook::jump(0x56CBDC, call_builtin_method_stub);
|
||||||
utils::hook::jump(0x56B726, vm_execute_stub);
|
utils::hook::jump(0x56B726, vm_execute_stub);
|
||||||
|
@ -19,4 +19,8 @@ namespace gsc
|
|||||||
{
|
{
|
||||||
void add(const std::string& name, const script_method& func);
|
void add(const std::string& name, const script_method& func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int make_array();
|
||||||
|
void add_array_key_value(unsigned int parent_id, const std::string& _key, const scripting::script_value& value);
|
||||||
|
void add_array_value(unsigned int parent_id, const scripting::script_value& value);
|
||||||
}
|
}
|
@ -15,33 +15,6 @@ namespace json
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
unsigned int make_array()
|
|
||||||
{
|
|
||||||
unsigned int index = 0;
|
|
||||||
const auto variable = game::AllocVariable(&index);
|
|
||||||
variable->w.type = game::SCRIPT_ARRAY;
|
|
||||||
variable->u.f.prev = 0;
|
|
||||||
variable->u.f.next = 0;
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_array_key_value(unsigned int parent_id, const std::string& _key, const scripting::script_value& value)
|
|
||||||
{
|
|
||||||
const auto key = game::SL_GetString(_key.data(), 0);
|
|
||||||
|
|
||||||
scripting::push_value(scripting::entity(parent_id));
|
|
||||||
scripting::push_value(value);
|
|
||||||
game::Scr_AddArrayStringIndexed(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_array_value(unsigned int parent_id, const scripting::script_value& value)
|
|
||||||
{
|
|
||||||
scripting::push_value(scripting::entity(parent_id));
|
|
||||||
scripting::push_value(value);
|
|
||||||
game::Scr_AddArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
nlohmann::json gsc_to_json(scripting::script_value value);
|
nlohmann::json gsc_to_json(scripting::script_value value);
|
||||||
|
|
||||||
nlohmann::json entity_to_array(unsigned int id)
|
nlohmann::json entity_to_array(unsigned int id)
|
||||||
@ -154,22 +127,22 @@ namespace json
|
|||||||
return obj.get<std::string>();
|
return obj.get<std::string>();
|
||||||
case (nlohmann::detail::value_t::array):
|
case (nlohmann::detail::value_t::array):
|
||||||
{
|
{
|
||||||
const auto arr = make_array();
|
const auto arr = gsc::make_array();
|
||||||
|
|
||||||
for (const auto& [key, value] : obj.items())
|
for (const auto& [key, value] : obj.items())
|
||||||
{
|
{
|
||||||
add_array_value(arr, json_to_gsc(value));
|
gsc::add_array_value(arr, json_to_gsc(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return scripting::entity(arr);
|
return scripting::entity(arr);
|
||||||
}
|
}
|
||||||
case (nlohmann::detail::value_t::object):
|
case (nlohmann::detail::value_t::object):
|
||||||
{
|
{
|
||||||
const auto arr = make_array();
|
const auto arr = gsc::make_array();
|
||||||
|
|
||||||
for (const auto& [key, value] : obj.items())
|
for (const auto& [key, value] : obj.items())
|
||||||
{
|
{
|
||||||
add_array_key_value(arr, key, json_to_gsc(value));
|
gsc::add_array_key_value(arr, key, json_to_gsc(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return scripting::entity(arr);
|
return scripting::entity(arr);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
|
#include "command.hpp"
|
||||||
|
|
||||||
#include "game/scripting/event.hpp"
|
#include "game/scripting/event.hpp"
|
||||||
#include "game/scripting/execution.hpp"
|
#include "game/scripting/execution.hpp"
|
||||||
@ -69,8 +70,8 @@ namespace scripting
|
|||||||
|
|
||||||
void g_shutdown_game_stub(const int free_scripts)
|
void g_shutdown_game_stub(const int free_scripts)
|
||||||
{
|
{
|
||||||
|
command::clear_script_commands();
|
||||||
replaced_functions.clear();
|
replaced_functions.clear();
|
||||||
|
|
||||||
g_shutdown_game_hook.invoke<void>(free_scripts);
|
g_shutdown_game_hook.invoke<void>(free_scripts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,9 +134,6 @@ namespace scripting
|
|||||||
g_shutdown_game_hook.create(0x50C100, g_shutdown_game_stub);
|
g_shutdown_game_hook.create(0x50C100, g_shutdown_game_stub);
|
||||||
|
|
||||||
scr_add_class_field_hook.create(0x567CD0, scr_add_class_field_stub);
|
scr_add_class_field_hook.create(0x567CD0, scr_add_class_field_stub);
|
||||||
//vm_notify_hook.create(0x569720, vm_notify_stub);
|
|
||||||
|
|
||||||
//scr_emit_function_hook.create(0x561400, scr_emit_function_stub);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,7 @@ namespace scripting
|
|||||||
{
|
{
|
||||||
const auto id = entity.get_entity_id();
|
const auto id = entity.get_entity_id();
|
||||||
|
|
||||||
|
stack_isolation _;
|
||||||
for (auto i = arguments.rbegin(); i != arguments.rend(); ++i)
|
for (auto i = arguments.rbegin(); i != arguments.rend(); ++i)
|
||||||
{
|
{
|
||||||
push_value(*i);
|
push_value(*i);
|
||||||
@ -149,16 +150,9 @@ namespace scripting
|
|||||||
|
|
||||||
const auto local_id = game::AllocThread(id);
|
const auto local_id = game::AllocThread(id);
|
||||||
const auto result = game::VM_Execute(local_id, pos, arguments.size());
|
const auto result = game::VM_Execute(local_id, pos, arguments.size());
|
||||||
|
game::RemoveRefToObject(result);
|
||||||
|
|
||||||
const auto value = get_return_value();
|
return get_return_value();
|
||||||
|
|
||||||
game::RemoveRefToValue(game::scr_VmPub->top->type, game::scr_VmPub->top->u);
|
|
||||||
game::scr_VmPub->top->type = (game::scriptType_e)0;
|
|
||||||
|
|
||||||
--game::scr_VmPub->top;
|
|
||||||
--game::scr_VmPub->inparamcount;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
script_value call_script_function(const entity& entity, const std::string& filename,
|
script_value call_script_function(const entity& entity, const std::string& filename,
|
||||||
|
@ -17,6 +17,15 @@ namespace game
|
|||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CmdArgs
|
||||||
|
{
|
||||||
|
int nesting;
|
||||||
|
int localClientNum[8];
|
||||||
|
int controllerIndex[8];
|
||||||
|
int argc[8];
|
||||||
|
const char** argv[8];
|
||||||
|
};
|
||||||
|
|
||||||
struct msg_t
|
struct msg_t
|
||||||
{
|
{
|
||||||
int overflowed;
|
int overflowed;
|
||||||
|
@ -18,8 +18,9 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<const char*(int index)> ConcatArgs{0x502150};
|
WEAK symbol<const char*(int index)> ConcatArgs{0x502150};
|
||||||
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x545680};
|
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x545680};
|
||||||
WEAK symbol<void(const char* cmdName, void(), cmd_function_t* allocedCmd)> Cmd_AddCommandInternal{0x0};
|
WEAK symbol<void(const char* cmdName, void(), cmd_function_t* allocedCmd)> Cmd_AddCommandInternal{0x545DF0};
|
||||||
WEAK symbol<const char*(int index)> Cmd_Argv{0x0};
|
WEAK symbol<void(const char* cmdName)> Cmd_RemoveCommand{0x545E20};
|
||||||
|
WEAK symbol<const char*(int index)> Cmd_Argv{0x467600};
|
||||||
|
|
||||||
WEAK symbol<const dvar_t*(const char*)> Dvar_FindVar{0x5BDCC0};
|
WEAK symbol<const dvar_t*(const char*)> Dvar_FindVar{0x5BDCC0};
|
||||||
|
|
||||||
@ -60,6 +61,8 @@ namespace game
|
|||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
|
|
||||||
|
WEAK symbol<CmdArgs> cmd_args{0x1C978D0};
|
||||||
|
|
||||||
WEAK symbol<int> g_script_error_level{0x20B21FC};
|
WEAK symbol<int> g_script_error_level{0x20B21FC};
|
||||||
WEAK symbol<jmp_buf> g_script_error{0x20B4218};
|
WEAK symbol<jmp_buf> g_script_error{0x20B4218};
|
||||||
|
|
||||||
|
@ -54,14 +54,14 @@ namespace utils
|
|||||||
return this->pool_.empty();
|
return this->pool_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*char* memory::allocator::duplicate_string(const std::string& string)
|
char* memory::allocator::duplicate_string(const std::string& string)
|
||||||
{
|
{
|
||||||
std::lock_guard _(this->mutex_);
|
std::lock_guard _(this->mutex_);
|
||||||
|
|
||||||
const auto data = memory::duplicate_string(string);
|
const auto data = memory::duplicate_string(string);
|
||||||
this->pool_.push_back(data);
|
this->pool_.push_back(data);
|
||||||
return data;
|
return data;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
void* memory::allocate(const size_t length)
|
void* memory::allocate(const size_t length)
|
||||||
{
|
{
|
||||||
@ -70,12 +70,12 @@ namespace utils
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*char* memory::duplicate_string(const std::string& string)
|
char* memory::duplicate_string(const std::string& string)
|
||||||
{
|
{
|
||||||
const auto new_string = allocate_array<char>(string.size() + 1);
|
const auto new_string = allocate_array<char>(string.size() + 1);
|
||||||
std::memcpy(new_string, string.data(), string.size());
|
std::memcpy(new_string, string.data(), string.size());
|
||||||
return new_string;
|
return new_string;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
void memory::free(void* data)
|
void memory::free(void* data)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ namespace utils
|
|||||||
|
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
|
|
||||||
//char* duplicate_string(const std::string& string);
|
char* duplicate_string(const std::string& string);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
@ -55,7 +55,7 @@ namespace utils
|
|||||||
return static_cast<T*>(allocate(count * sizeof(T)));
|
return static_cast<T*>(allocate(count * sizeof(T)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//static char* duplicate_string(const std::string& string);
|
static char* duplicate_string(const std::string& string);
|
||||||
|
|
||||||
static void free(void* data);
|
static void free(void* data);
|
||||||
static void free(const void* data);
|
static void free(const void* data);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user