mirror of
https://github.com/fedddddd/iw5-gsc-utils.git
synced 2025-04-20 21:05: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 "scheduler.hpp"
|
||||
#include "scripting.hpp"
|
||||
#include "command.hpp"
|
||||
|
||||
#include "game/scripting/event.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
|
||||
{
|
||||
public:
|
||||
@ -276,6 +304,32 @@ namespace gsc
|
||||
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(0x56CBDC, call_builtin_method_stub);
|
||||
utils::hook::jump(0x56B726, vm_execute_stub);
|
||||
|
@ -19,4 +19,8 @@ namespace gsc
|
||||
{
|
||||
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
|
||||
{
|
||||
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 entity_to_array(unsigned int id)
|
||||
@ -154,22 +127,22 @@ namespace json
|
||||
return obj.get<std::string>();
|
||||
case (nlohmann::detail::value_t::array):
|
||||
{
|
||||
const auto arr = make_array();
|
||||
const auto arr = gsc::make_array();
|
||||
|
||||
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);
|
||||
}
|
||||
case (nlohmann::detail::value_t::object):
|
||||
{
|
||||
const auto arr = make_array();
|
||||
const auto arr = gsc::make_array();
|
||||
|
||||
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);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
#include "command.hpp"
|
||||
|
||||
#include "game/scripting/event.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
@ -69,8 +70,8 @@ namespace scripting
|
||||
|
||||
void g_shutdown_game_stub(const int free_scripts)
|
||||
{
|
||||
command::clear_script_commands();
|
||||
replaced_functions.clear();
|
||||
|
||||
g_shutdown_game_hook.invoke<void>(free_scripts);
|
||||
}
|
||||
|
||||
@ -133,9 +134,6 @@ namespace scripting
|
||||
g_shutdown_game_hook.create(0x50C100, g_shutdown_game_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();
|
||||
|
||||
stack_isolation _;
|
||||
for (auto i = arguments.rbegin(); i != arguments.rend(); ++i)
|
||||
{
|
||||
push_value(*i);
|
||||
@ -149,16 +150,9 @@ namespace scripting
|
||||
|
||||
const auto local_id = game::AllocThread(id);
|
||||
const auto result = game::VM_Execute(local_id, pos, arguments.size());
|
||||
game::RemoveRefToObject(result);
|
||||
|
||||
const auto value = 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;
|
||||
return get_return_value();
|
||||
}
|
||||
|
||||
script_value call_script_function(const entity& entity, const std::string& filename,
|
||||
|
@ -17,6 +17,15 @@ namespace game
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct CmdArgs
|
||||
{
|
||||
int nesting;
|
||||
int localClientNum[8];
|
||||
int controllerIndex[8];
|
||||
int argc[8];
|
||||
const char** argv[8];
|
||||
};
|
||||
|
||||
struct msg_t
|
||||
{
|
||||
int overflowed;
|
||||
|
@ -18,8 +18,9 @@ namespace game
|
||||
|
||||
WEAK symbol<const char*(int index)> ConcatArgs{0x502150};
|
||||
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<const char*(int index)> Cmd_Argv{0x0};
|
||||
WEAK symbol<void(const char* cmdName, void(), cmd_function_t* allocedCmd)> Cmd_AddCommandInternal{0x545DF0};
|
||||
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};
|
||||
|
||||
@ -60,6 +61,8 @@ namespace game
|
||||
|
||||
// Variables
|
||||
|
||||
WEAK symbol<CmdArgs> cmd_args{0x1C978D0};
|
||||
|
||||
WEAK symbol<int> g_script_error_level{0x20B21FC};
|
||||
WEAK symbol<jmp_buf> g_script_error{0x20B4218};
|
||||
|
||||
|
@ -54,14 +54,14 @@ namespace utils
|
||||
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_);
|
||||
|
||||
const auto data = memory::duplicate_string(string);
|
||||
this->pool_.push_back(data);
|
||||
return data;
|
||||
}*/
|
||||
}
|
||||
|
||||
void* memory::allocate(const size_t length)
|
||||
{
|
||||
@ -70,12 +70,12 @@ namespace utils
|
||||
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);
|
||||
std::memcpy(new_string, string.data(), string.size());
|
||||
return new_string;
|
||||
}*/
|
||||
}
|
||||
|
||||
void memory::free(void* data)
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ namespace utils
|
||||
|
||||
bool empty() const;
|
||||
|
||||
//char* duplicate_string(const std::string& string);
|
||||
char* duplicate_string(const std::string& string);
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
@ -55,7 +55,7 @@ namespace utils
|
||||
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(const void* data);
|
||||
|
Loading…
x
Reference in New Issue
Block a user