整理初版

This commit is contained in:
2026-05-08 19:03:33 +08:00
parent a9af16962c
commit a605fb2bea
352 changed files with 0 additions and 7278 deletions

View File

@@ -0,0 +1,385 @@
#pragma once
#include "frida-gum.h"
#include <fcntl.h>
#include <unistd.h>
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <mutex>
#include <iostream>
extern HSQUIRRELVM v;
extern std::recursive_mutex SqMtx;
#define CONTAINS_STRING(str, substr) (str == substr)
typedef struct {
const SQChar* name;
size_t offset;
} CpuContextMember;
// HookFunc
struct _ExampleListener
{
GObject parent;
guint num_calls;
std::vector<std::string> ArgumentCount;
std::string RetType;
HSQOBJECT CallBackOnEnter;
HSQOBJECT CallBackOnLeave;
SQUserPointer FuncAddress;
};
enum _ExampleHookId
{
EXAMPLE_HOOK_OPEN,
EXAMPLE_HOOK_CLOSE
};
typedef struct _ExampleListener ExampleListener;
typedef enum _ExampleHookId ExampleHookId;
static void example_listener_iface_init(gpointer g_iface, gpointer iface_data);
static GumInterceptor* interceptor;
static std::thread::id Zhuxianc = std::this_thread::get_id();
#define EXAMPLE_TYPE_LISTENER (example_listener_get_type())
G_DECLARE_FINAL_TYPE(ExampleListener, example_listener, EXAMPLE, LISTENER, GObject)
G_DEFINE_TYPE_EXTENDED(ExampleListener, example_listener, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE(GUM_TYPE_INVOCATION_LISTENER, example_listener_iface_init))
// 自定义替换函数
static void replacement_function(GumInvocationContext* context)
{
// 在这里执行你的逻辑
// gum_print("自定义逻辑已执行!\n");
// 跳过原函数,直接返回
// 如果需要修改返回值,可以通过 context->cpu_context 修改寄存器
}
static SQInteger L_HookFunc(HSQUIRRELVM v)
{
static bool InitFlag = false;
if (!InitFlag)
{
InitFlag = true;
gum_init_embedded();
interceptor = gum_interceptor_obtain();
}
GumInvocationListener* listener = (GumInvocationListener*)g_object_new(EXAMPLE_TYPE_LISTENER, NULL);
// 得到函数地址
SQUserPointer FuncAddress;
sq_getuserpointer(v, 2, &FuncAddress);
// 遍历参数类型数组
std::vector<std::string> ParameterType;
sq_pushnull(v); // null iterator
while (SQ_SUCCEEDED(sq_next(v, 3)))
{
const SQChar* path;
sq_getstring(v, -1, &path);
ParameterType.push_back(path);
sq_pop(v, 2);
}
sq_pop(v, 1);
// 得到入口回调函数
HSQOBJECT CallBackOnEnter;
sq_getstackobj(v, 4, &CallBackOnEnter);
// 必须增加一次引用一会记得删除 不然这个函数会被释放
sq_addref(v, &CallBackOnEnter);
// 得到出口回调函数
HSQOBJECT CallBackOnLeave;
sq_getstackobj(v, 5, &CallBackOnLeave);
// 必须增加一次引用一会记得删除 不然这个函数会被释放
sq_addref(v, &CallBackOnLeave);
EXAMPLE_LISTENER(listener)->ArgumentCount = ParameterType;
// EXAMPLE_LISTENER(listener)->RetType = std::string(RetBuf);
EXAMPLE_LISTENER(listener)->CallBackOnEnter = CallBackOnEnter;
EXAMPLE_LISTENER(listener)->CallBackOnLeave = CallBackOnLeave;
EXAMPLE_LISTENER(listener)->FuncAddress = FuncAddress;
gum_interceptor_begin_transaction(interceptor);
gum_interceptor_attach(interceptor, GSIZE_TO_POINTER(FuncAddress), listener, GSIZE_TO_POINTER(FuncAddress));
gum_interceptor_end_transaction(interceptor);
sq_pushuserpointer(v, listener);
return 1;
}
static SQInteger L_DeHookFunc(HSQUIRRELVM v)
{
// 得到函数地址
SQUserPointer FuncAddress;
sq_getuserpointer(v, 2, &FuncAddress);
GumInvocationListener* listener = (GumInvocationListener*)FuncAddress;
gum_interceptor_detach(interceptor, listener);
return 0;
}
static void example_listener_on_enter(GumInvocationListener* listener, GumInvocationContext* ic)
{
gpointer ReturnAddress = gum_invocation_context_get_return_address(ic);
ExampleListener* self = EXAMPLE_LISTENER(listener);
// std::cout << "调用点: " << self->FuncAddress << std::endl;
std::lock_guard<std::recursive_mutex> lock(SqMtx);
// 执行虚拟机Main函数
SQInteger top = sq_gettop(v); // saves the stack size before the call
//传入返回地址
sq_pushroottable(v);
sq_pushstring(v, _SC("_Haker_SetNextReturnAddress"), -1);
if (SQ_SUCCEEDED(sq_get(v, -2)))
{
sq_pushroottable(v);
sq_pushuserpointer(v, ReturnAddress);
sq_call(v, 2, SQFalse, SQTrue);
}
sq_settop(v, top);
//传入CPU上下文
sq_pushroottable(v);
sq_pushstring(v, _SC("_Haker_SetCpuContext"), -1);
if (SQ_SUCCEEDED(sq_get(v, -2)))
{
sq_pushroottable(v);
sq_newtable(v);
struct TableEntry
{
const SQChar* key;
SQUserPointer value;
} entries[] = {
{_SC("eip"), (SQUserPointer)ic->cpu_context->eip},
{_SC("edi"), (SQUserPointer)ic->cpu_context->edi},
{_SC("esi"), (SQUserPointer)ic->cpu_context->esi},
{_SC("ebp"), (SQUserPointer)ic->cpu_context->ebp},
{_SC("esp"), (SQUserPointer)ic->cpu_context->esp},
{_SC("ebx"), (SQUserPointer)ic->cpu_context->ebx},
{_SC("edx"), (SQUserPointer)ic->cpu_context->edx},
{_SC("ecx"), (SQUserPointer)ic->cpu_context->ecx},
{_SC("eax"), (SQUserPointer)ic->cpu_context->eax},
};
for (const auto& entry : entries)
{
sq_pushstring(v, entry.key, -1);
sq_pushuserpointer(v, entry.value);
sq_newslot(v, -3, SQFalse);
}
sq_call(v, 2, SQFalse, SQTrue);
}
sq_settop(v, top);
sq_pushobject(v, self->CallBackOnEnter);
sq_pushroottable(v);
sq_newarray(v, 0);
for (size_t i = 0; i < self->ArgumentCount.size() - 1; i++)
{
void* Abuf = gum_invocation_context_get_nth_argument(ic, i);
if (CONTAINS_STRING(self->ArgumentCount[i], "int"))
sq_pushinteger(v, (int)Abuf);
else if (CONTAINS_STRING(self->ArgumentCount[i], "float"))
{
SQFloat* a = reinterpret_cast<float*>(&Abuf);
sq_pushfloat(v, *(SQFloat*)a);
}
else if (CONTAINS_STRING(self->ArgumentCount[i], "bool"))
sq_pushbool(v, (bool)Abuf);
else if (CONTAINS_STRING(self->ArgumentCount[i], "string"))
sq_pushstring(v, (char*)Abuf, -1);
else if (CONTAINS_STRING(self->ArgumentCount[i], "pointer"))
sq_pushuserpointer(v, (void*)Abuf);
else if (CONTAINS_STRING(self->ArgumentCount[i], "short"))
sq_pushinteger(v, (int)Abuf);
else if (CONTAINS_STRING(self->ArgumentCount[i], "char"))
sq_pushinteger(v, (int)Abuf);
else
sq_pushuserpointer(v, (void*)Abuf);
sq_arrayappend(v, -2);
}
sq_call(v, 2, SQTrue, SQTrue); // calls the function
if (sq_gettype(v, -1) == OT_ARRAY)
{
sq_pushnull(v); // null iterator
int Idx = 0;
while (SQ_SUCCEEDED(sq_next(v, -2)))
{
if (CONTAINS_STRING(self->ArgumentCount[Idx], "int"))
{
SQInteger Abuf;
sq_getinteger(v, -1, &Abuf);
gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount[Idx], "float"))
{
SQFloat Abuf;
sq_getfloat(v, -1, &Abuf);
gum_invocation_context_replace_nth_argument(ic, Idx, &Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount[Idx], "bool"))
{
SQBool Abuf;
sq_getbool(v, -1, &Abuf);
gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount[Idx], "string"))
{
const SQChar* Abuf;
sq_getstring(v, -1, &Abuf);
gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount[Idx], "pointer"))
{
SQUserPointer Abuf;
sq_getuserpointer(v, -1, &Abuf);
gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount[Idx], "short"))
{
SQInteger Abuf;
sq_getinteger(v, -1, &Abuf);
gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount[Idx], "char"))
{
SQInteger Abuf;
sq_getinteger(v, -1, &Abuf);
char CBUF = Abuf;
gum_invocation_context_replace_nth_argument(ic, Idx, (void*)CBUF);
}
Idx++;
sq_pop(v, 2);
}
sq_pop(v, 1);
sq_settop(v, top); // restores the original stack size
return;
}
sq_settop(v, top); // restores the original stack size
return;
}
static void example_listener_on_leave(GumInvocationListener* listener, GumInvocationContext* ic)
{
ExampleListener* self = EXAMPLE_LISTENER(listener);
std::lock_guard<std::recursive_mutex> lock(SqMtx);
// 执行虚拟机Main函数
SQInteger top = sq_gettop(v); // saves the stack size before the call
sq_pushobject(v, self->CallBackOnLeave);
sq_pushroottable(v);
sq_newarray(v, 0);
for (size_t i = 0; i < self->ArgumentCount.size(); i++)
{
void* Abuf;
if (i == (self->ArgumentCount.size() - 1))
Abuf = gum_invocation_context_get_return_value(ic);
else
Abuf = gum_invocation_context_get_nth_argument(ic, i);
if (CONTAINS_STRING(self->ArgumentCount[i], "int"))
sq_pushinteger(v, (int)Abuf);
else if (CONTAINS_STRING(self->ArgumentCount[i], "float"))
{
SQFloat* a = reinterpret_cast<float*>(&Abuf);
sq_pushfloat(v, *(SQFloat*)a);
}
else if (CONTAINS_STRING(self->ArgumentCount[i], "bool"))
sq_pushbool(v, (bool)Abuf);
else if (CONTAINS_STRING(self->ArgumentCount[i], "string"))
sq_pushstring(v, (char*)Abuf, -1);
else if (CONTAINS_STRING(self->ArgumentCount[i], "pointer"))
sq_pushuserpointer(v, (void*)Abuf);
else if (CONTAINS_STRING(self->ArgumentCount[i], "short"))
sq_pushinteger(v, (int)Abuf);
else if (CONTAINS_STRING(self->ArgumentCount[i], "char"))
sq_pushinteger(v, (int)Abuf);
else
sq_pushuserpointer(v, (void*)Abuf);
sq_arrayappend(v, -2);
}
sq_call(v, 2, SQTrue, SQTrue); // calls the function
if (sq_gettype(v, -1) != OT_NULL)
{
if (CONTAINS_STRING(self->ArgumentCount.back(), "int"))
{
SQInteger Abuf;
sq_getinteger(v, -1, &Abuf);
gum_invocation_context_replace_return_value(ic, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount.back(), "float"))
{
SQFloat Abuf;
sq_getfloat(v, -1, &Abuf);
gum_invocation_context_replace_return_value(ic, &Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount.back(), "bool"))
{
SQBool Abuf;
sq_getbool(v, -1, &Abuf);
gum_invocation_context_replace_return_value(ic, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount.back(), "string"))
{
const SQChar* Abuf;
sq_getstring(v, -1, &Abuf);
gum_invocation_context_replace_return_value(ic, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount.back(), "pointer"))
{
SQUserPointer Abuf;
sq_getuserpointer(v, -1, &Abuf);
gum_invocation_context_replace_return_value(ic, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount.back(), "short"))
{
SQInteger Abuf;
sq_getinteger(v, -1, &Abuf);
gum_invocation_context_replace_return_value(ic, (void*)Abuf);
}
else if (CONTAINS_STRING(self->ArgumentCount.back(), "char"))
{
SQInteger Abuf;
sq_getinteger(v, -1, &Abuf);
char CBUF = Abuf;
gum_invocation_context_replace_return_value(ic, (void*)Abuf);
}
}
sq_settop(v, top);
}
static void example_listener_class_init(ExampleListenerClass* klass)
{
(void)EXAMPLE_IS_LISTENER;
(void)glib_autoptr_cleanup_ExampleListener;
}
static void example_listener_iface_init(gpointer g_iface, gpointer iface_data)
{
GumInvocationListenerInterface* iface = (GumInvocationListenerInterface*)g_iface;
iface->on_enter = example_listener_on_enter;
iface->on_leave = example_listener_on_leave;
}
static void example_listener_init(ExampleListener* self)
{
}
static void RegisterActiveHook(HSQUIRRELVM v)
{
register_World_func(v, L_HookFunc, _SC("Sq_HookFunc"));
register_World_func(v, L_DeHookFunc, _SC("Sq_DeHookFunc"));
}

102
src/script/SqrReg_Asset.hpp Normal file
View File

@@ -0,0 +1,102 @@
#pragma once
#include "PVF_IO.hpp"
static SQInteger Asset_LoadScript(HSQUIRRELVM v)
{
// 获得路径
const SQChar *Path;
sq_getstring(v, 2, &Path);
PVF_IO *pvf = new PVF_IO(Path);
pvf->Init();
sq_pushuserpointer(v, pvf);
return 1;
}
static SQInteger Asset_GetPvfFileSize(HSQUIRRELVM v)
{
// 获取PVF指针
SQUserPointer Pvfbuf;
// 获得路径
const SQChar *Path;
sq_getuserpointer(v, 2, &Pvfbuf);
sq_getstring(v, 3, &Path);
PVF_IO *Pvf = (PVF_IO *)Pvfbuf;
auto Info = Pvf->GetFileInfo(Path);
if (Info)
sq_pushinteger(v, Info->Length);
else
sq_pushnull(v);
return 1;
}
static SQInteger Asset_GetPvfFile(HSQUIRRELVM v)
{
// 获取PVF指针
SQUserPointer Pvfbuf, blobp;
// 获得路径
const SQChar *Path;
sq_getuserpointer(v, 2, &Pvfbuf);
sq_getstring(v, 3, &Path);
sqstd_getblob(v, 4, &blobp);
PVF_IO *Pvf = (PVF_IO *)Pvfbuf;
Pvf->LoadFileToBlob(v, Path, blobp);
return 0;
}
static SQInteger Asset_GetPvfBinString(HSQUIRRELVM v)
{
// 获取PVF指针
SQUserPointer Pvfbuf;
// 获得Key
SQInteger Key;
sq_getuserpointer(v, 2, &Pvfbuf);
sq_getinteger(v, 3, &Key);
PVF_IO *Pvf = (PVF_IO *)Pvfbuf;
std::string value = Pvf->GetBinString(Key);
sq_pushstring(v, value.c_str(), value.length());
return 1;
}
static SQInteger Asset_GetPvfLoadString(HSQUIRRELVM v)
{
// 获取PVF指针
SQUserPointer Pvfbuf;
// 获取类型
const SQChar *Type;
// 获得Key
const SQChar *Key;
sq_getuserpointer(v, 2, &Pvfbuf);
sq_getstring(v, 3, &Type);
sq_getstring(v, 4, &Key);
PVF_IO *Pvf = (PVF_IO *)Pvfbuf;
std::string value = Pvf->GetLoadString(Type, Key);
value = value.c_str();
sq_pushstring(v, value.c_str(), value.length());
return 1;
}
void RegisterAssetNutApi(const SQChar *funcName, SQFUNCTION funcAddr, HSQUIRRELVM v)
{
sq_pushroottable(v);
sq_pushstring(v, funcName, -1);
sq_newclosure(v, funcAddr, 0);
sq_newslot(v, -3, false);
sq_poptop(v);
}
void RegisterAsset(HSQUIRRELVM v)
{
RegisterAssetNutApi(_SC("Asset_LoadScript"), Asset_LoadScript, v);
RegisterAssetNutApi(_SC("Asset_GetPvfFileSize"), Asset_GetPvfFileSize, v);
RegisterAssetNutApi(_SC("Asset_GetPvfFile"), Asset_GetPvfFile, v);
RegisterAssetNutApi(_SC("Asset_GetPvfBinString"), Asset_GetPvfBinString, v);
RegisterAssetNutApi(_SC("Asset_GetPvfLoadString"), Asset_GetPvfLoadString, v);
}

View File

@@ -0,0 +1,52 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <iostream>
template <typename R, typename A, typename... ARG>
R CallBattleField(A call_addr, const ARG... arguments)
{
if (!call_addr)
{
return R();
}
const auto control = reinterpret_cast<R (*)(ARG...)>(call_addr);
try
{
return control(arguments...);
}
catch (...)
{
}
return R();
}
// 获取副本对象
static SQInteger BattleField_GetDgn(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQUserPointer B = CallBattleField<void *>(0x80FDCFC, P);
sq_pushuserpointer(v, B);
return 1;
}
static SQInteger register_BattleField_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
{
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
static void RegisterBattleField(HSQUIRRELVM v)
{
// 获取副本对象
register_BattleField_func(v, BattleField_GetDgn, _SC("Sq_BattleField_GetDgn"));
}

547
src/script/SqrReg_Dio.hpp Normal file
View File

@@ -0,0 +1,547 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <asio.hpp>
#include <asio/ssl.hpp>
#include <asio/basic_socket_streambuf.hpp>
#include <iostream>
#include <thread>
#include <atomic>
#include <unordered_map>
#include <mutex>
#include <memory> // 新增:用于 std::unique_ptr
#include <string>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <stdint.h>
// 全局变量声明需在cpp文件中定义
extern HSQUIRRELVM v;
extern std::recursive_mutex SqMtx;
using tcp = asio::ip::tcp;
// ====================== 工具函数 ======================
// 字符串转小写
std::string to_lower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return std::tolower(c); });
return s;
}
// 修剪字符串两端空格
std::string trim(std::string s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
[](unsigned char c) { return !std::isspace(c); }));
s.erase(std::find_if(s.rbegin(), s.rend(),
[](unsigned char c) { return !std::isspace(c); }).base(), s.end());
return s;
}
// 解析 URL分离路径和查询参数
void parse_url(const std::string& url, std::string& path, std::string& query) {
size_t query_pos = url.find('?');
if (query_pos == std::string::npos) {
path = url;
query = "";
}
else {
path = url.substr(0, query_pos);
query = url.substr(query_pos + 1);
}
}
// ====================== HTTP 头解析结构体 ======================
struct HttpRequestHeader {
std::string method; // GET/POST/PUT/DELETE 等
std::string path; // 请求路径(如 /api/test
std::string version; // HTTP/1.1 / HTTP/1.0
std::string query_string; // URL 查询参数(如 ?id=1&name=test
// 头部键值对(统一转小写,避免大小写问题)
std::unordered_map<std::string, std::string> headers;
// 便捷获取头部值(兼容大小写)
std::string get_header(const std::string& key) const {
std::string lower_key = to_lower(key);
auto it = headers.find(lower_key);
return it != headers.end() ? it->second : "";
}
};
// ====================== HTTP 头解析函数 ======================
HttpRequestHeader parse_http_header(const std::string& raw_header) {
HttpRequestHeader result;
std::istringstream iss(raw_header);
std::string line;
bool first_line_parsed = false;
// 第一步:解析请求首行(仅解析第一行,避免重复)
while (std::getline(iss, line)) {
// 移除行尾的 \r
if (!line.empty() && line.back() == '\r') {
line.pop_back();
}
line = trim(line);
// 跳过空行
if (line.empty()) {
continue;
}
// 仅解析第一个非空行作为请求首行
if (!first_line_parsed) {
std::string url;
std::istringstream line_iss(line);
line_iss >> result.method >> url >> result.version;
parse_url(url, result.path, result.query_string);
std::transform(result.method.begin(), result.method.end(), result.method.begin(),
[](unsigned char c) { return std::toupper(c); });
first_line_parsed = true;
continue;
}
// 解析头部键值对
size_t colon_pos = line.find(':');
if (colon_pos == std::string::npos) {
continue;
}
std::string key = trim(line.substr(0, colon_pos));
std::string value = trim(line.substr(colon_pos + 1));
result.headers[to_lower(key)] = value;
}
return result;
}
// ====================== 读取完整原始请求 ======================
std::string read_full_raw_request(tcp::socket& socket, HttpRequestHeader& header_out) {
asio::streambuf buf;
std::string full_request;
asio::error_code ec;
try {
// 第一步:读取头部(直到 \r\n\r\n
size_t header_bytes = asio::read_until(socket, buf, "\r\n\r\n", ec);
if (ec) {
throw asio::system_error(ec);
}
// 提取头部内容
std::string header_str(asio::buffer_cast<const char*>(buf.data()), header_bytes);
full_request = header_str;
// 安全清理头部末尾的 \r\n\r\n核心修复先判断是否找到
size_t end_header_pos = header_str.find("\r\n\r\n"); // 用 find 而非 find_last_of精准匹配结束符
if (end_header_pos != std::string::npos) {
// 只保留头部内容,截断后面的空行
header_str = header_str.substr(0, end_header_pos);
}
// 解析头部
header_out = parse_http_header(header_str);
// 第二步:读取请求体(严格按 Content-Length 读取)
size_t content_len = 0;
std::string cl_str = header_out.get_header("Content-Length");
if (!cl_str.empty()) {
try {
content_len = std::stoul(cl_str);
}
catch (...) {
content_len = 0;
}
}
// 清空缓冲区中已读取的头部数据
buf.consume(header_bytes);
// 读取请求体(防越界)
if (content_len > 0) {
// 先检查剩余缓冲区是否足够,避免读取超限
size_t buf_available = buf.size();
if (buf_available < content_len) {
// 读取剩余需要的字节
asio::read(socket, buf, asio::transfer_exactly(content_len - buf_available), ec);
if (ec && ec != asio::error::eof) {
throw asio::system_error(ec);
}
}
// 提取请求体(防缓冲区数据不足)
size_t actual_read = std::min(buf.size(), content_len);
std::string body_str(asio::buffer_cast<const char*>(buf.data()), actual_read);
full_request += body_str;
// 清理缓冲区
buf.consume(actual_read);
}
}
catch (...) {
throw;
}
return full_request;
}
// ====================== 将 HttpRequestHeader 转为 Squirrel Table ======================
void push_http_header_to_squirrel(HSQUIRRELVM v, const HttpRequestHeader& header) {
// 1. 创建空 Table
sq_newtable(v);
// 2. 设置基础字段method/path/version/query_string
// method
sq_pushstring(v, _SC("method"), -1);
sq_pushstring(v, header.method.c_str(), -1);
sq_rawset(v, -3);
// path
sq_pushstring(v, _SC("path"), -1);
sq_pushstring(v, header.path.c_str(), -1);
sq_rawset(v, -3);
// version
sq_pushstring(v, _SC("version"), -1);
sq_pushstring(v, header.version.c_str(), -1);
sq_rawset(v, -3);
// query_string
sq_pushstring(v, _SC("query_string"), -1);
sq_pushstring(v, header.query_string.c_str(), -1);
sq_rawset(v, -3);
// 3. 创建 headers 子 Table
sq_pushstring(v, _SC("headers"), -1);
sq_newtable(v);
// 遍历头部键值对,写入子 Table
for (const auto& pair : header.headers) {
sq_pushstring(v, pair.first.c_str(), -1); // 键(小写)
sq_pushstring(v, pair.second.c_str(), -1); // 值
sq_rawset(v, -3);
}
// 将 headers 子 Table 写入主 Table
sq_rawset(v, -3);
}
// ====================== 处理客户端请求 ======================
void handle_client(tcp::socket* socket, HSQOBJECT HttpServerObject) {
if (!socket || !socket->is_open()) {
std::cerr << "无效的 socket 连接" << std::endl;
return;
}
try {
// 读取完整请求并解析头部
HttpRequestHeader header;
std::string full_request = read_full_raw_request(*socket, header);
// 加锁操作 Squirrel VMlock_guard 自动管理锁生命周期)
std::lock_guard<std::recursive_mutex> lock(SqMtx);
// 执行 Squirrel 的 Event 函数
SQInteger top = sq_gettop(v); // 保存栈状态
sq_pushobject(v, HttpServerObject);
sq_pushstring(v, _SC("Event"), -1);
if (SQ_SUCCEEDED(sq_get(v, -2))) {
// 压入函数参数:
// 参数1HttpServerObjectthis
sq_pushobject(v, HttpServerObject);
// 参数2socket 指针userpointer
sq_pushuserpointer(v, socket);
// 参数3解析后的 header table
push_http_header_to_squirrel(v, header);
// 参数4完整原始请求字符串
size_t body_start_pos = full_request.find("\r\n\r\n");
std::string request_body = (body_start_pos != std::string::npos) ? full_request.substr(body_start_pos + 4) : "";
sq_pushstring(v, request_body.c_str(), request_body.size());
// 调用函数:参数数量=4无返回值开启错误捕获
sq_call(v, 4, SQFalse, SQTrue);
}
sq_settop(v, top); // 恢复栈状态
}
catch (const asio::system_error& e) {
std::cerr << "网络错误: " << e.what() << " (错误码: " << e.code() << ")" << std::endl;
}
catch (const std::exception& e) {
std::cerr << "处理请求错误: " << e.what() << std::endl;
}
catch (...) {
std::cerr << "未知错误" << std::endl;
}
}
// ====================== 服务器上下文(支持多实例) ======================
struct HttpServerCtx {
uint64_t server_id; // 唯一服务器ID多实例核心
std::atomic<bool> running{ true }; // 退出标志atomic不可拷贝
HSQUIRRELVM vm; // Squirrel VM
HSQOBJECT http_server_obj; // 保存的对象
asio::io_context* io_context = nullptr; // IO上下文用于停止
std::string host; // 记录主机(调试用)
std::string port; // 记录端口(调试用)
// 禁用拷贝构造和赋值(显式声明,避免误拷贝)
HttpServerCtx(const HttpServerCtx&) = delete;
HttpServerCtx& operator=(const HttpServerCtx&) = delete;
// 允许移动构造用于unique_ptr
HttpServerCtx(HttpServerCtx&&) = default;
HttpServerCtx& operator=(HttpServerCtx&&) = default;
// 构造函数
HttpServerCtx() = default;
HttpServerCtx(uint64_t id, HSQUIRRELVM vm_ptr, HSQOBJECT obj, const std::string& h, const std::string& p)
: server_id(id), vm(vm_ptr), http_server_obj(obj), host(h), port(p) {
}
};
// ====================== 全局服务器管理核心修复用unique_ptr存储避免拷贝 ======================
static std::unordered_map<uint64_t, std::unique_ptr<HttpServerCtx>> g_server_ctxs;
static std::atomic<uint64_t> g_next_server_id{ 1 }; // 自增唯一IDatomic不可拷贝直接用
static std::mutex g_server_mutex; // 保护全局容器
// ====================== 服务器主函数 ======================
void start_server(uint64_t server_id, const std::string& host, const std::string& port) {
// 查找上下文(加锁)
std::unique_lock<std::mutex> lock(g_server_mutex);
auto it = g_server_ctxs.find(server_id);
if (it == g_server_ctxs.end()) {
std::cerr << "服务器上下文不存在 (ID: " << server_id << ")" << std::endl;
return;
}
HttpServerCtx* ctx = it->second.get(); // 获取指针,不拷贝
lock.unlock(); // 手动解锁
asio::io_context io_context;
ctx->io_context = &io_context; // 关联IO上下文
try {
tcp::acceptor acceptor(io_context, tcp::endpoint(asio::ip::make_address(host), std::stoi(port)));
std::cout << "Server [" << server_id << "] listening on " << host << ":" << port << std::endl;
// 循环监听(支持退出)
while (ctx->running.load(std::memory_order_relaxed)) { // 原子操作读取
tcp::socket* socket = new tcp::socket(io_context);
try {
acceptor.accept(*socket);
// 启动客户端处理线程
std::thread(handle_client, std::move(socket), ctx->http_server_obj).detach();
}
catch (const asio::system_error& e) {
delete socket; // 中断时释放Socket
if (e.code() != asio::error::operation_aborted && ctx->running.load(std::memory_order_relaxed)) {
std::cerr << "Server [" << server_id << "] Accept error: " << e.what() << std::endl;
}
}
}
}
catch (const std::exception& e) {
std::cerr << "Server [" << server_id << "] error: " << e.what() << std::endl;
}
// 停止IO上下文
io_context.stop();
std::cout << "Server [" << server_id << "] stopped" << std::endl;
}
// ====================== Squirrel 绑定函数 - 创建HTTP客户端 ======================
static SQInteger CreateHttp(HSQUIRRELVM v) {
const SQChar* Host;
sq_getstring(v, 2, &Host);
const SQChar* Service;
sq_getstring(v, 3, &Service);
const SQChar* Content;
sq_getstring(v, 4, &Content);
try {
asio::io_context ioContext;
asio::ip::tcp::resolver resolver(ioContext);
auto endpoints = resolver.resolve(Host, Service);
asio::ip::tcp::socket socket(ioContext);
asio::connect(socket, endpoints);
// 发送HTTP请求
std::string request = Content;
asio::write(socket, asio::buffer(request));
// 读取响应
asio::streambuf response;
asio::error_code error;
while (asio::read(socket, response, asio::transfer_at_least(1), error)) {}
if (error && error != asio::error::eof) {
throw asio::system_error(error);
}
// 将响应内容返回
std::istream responseStream(&response);
std::ostringstream oss;
oss << responseStream.rdbuf();
sq_pushstring(v, oss.str().c_str(), -1);
return 1;
}
catch (const std::exception& e) {
return sq_throwerror(v, e.what());
}
catch (...) {
return sq_throwerror(v, _SC("Unknown error occurred"));
}
}
// ====================== Squirrel 绑定函数 - 创建HTTP服务器核心修复避免拷贝atomic ======================
static SQInteger CreateHttpServer(HSQUIRRELVM v) {
const SQChar* host = nullptr;
const SQChar* port = nullptr;
HSQOBJECT HttpServerObject;
// 1. 参数校验
if (SQ_FAILED(sq_getstring(v, 2, &host)) ||
SQ_FAILED(sq_getstring(v, 3, &port)) ||
SQ_FAILED(sq_getstackobj(v, 4, &HttpServerObject))) {
sq_pushstring(v, _SC("param error: need (host:str, port:str, obj:HSQOBJECT)"), -1);
return SQ_ERROR;
}
// 2. 生成唯一服务器ID
uint64_t server_id = g_next_server_id.fetch_add(1, std::memory_order_relaxed);
try {
// 3. 动态创建上下文(避免拷贝)
auto ctx_ptr = std::unique_ptr<HttpServerCtx>(new HttpServerCtx(server_id, v, HttpServerObject, std::string(host), std::string(port)));
sq_addref(v, &ctx_ptr->http_server_obj); // 增加引用
// 4. 加锁存入全局(移动语义,不拷贝)
std::lock_guard<std::mutex> lock(g_server_mutex);
g_server_ctxs[server_id] = std::move(ctx_ptr); // 移动unique_ptr不拷贝atomic
// 5. 启动服务器线程
std::thread server_thread(start_server, server_id, std::string(host), std::string(port));
server_thread.detach();
// 6. 返回唯一ID给Squirrel
sq_pushinteger(v, static_cast<SQInteger>(server_id));
return 1;
}
catch (...) {
// 异常清理
sq_release(v, &HttpServerObject); // 直接释放传入的对象
std::lock_guard<std::mutex> lock(g_server_mutex);
g_server_ctxs.erase(server_id);
sq_pushbool(v, false);
return 1;
}
}
// ====================== Squirrel 绑定函数 - 停止HTTP服务器 ======================
static SQInteger StopHttpServer(HSQUIRRELVM v) {
SQInteger server_id_int;
if (SQ_FAILED(sq_getinteger(v, 2, &server_id_int)) || server_id_int <= 0) {
sq_pushstring(v, _SC("invalid server ID"), -1);
return SQ_ERROR;
}
uint64_t server_id = static_cast<uint64_t>(server_id_int);
std::lock_guard<std::mutex> lock(g_server_mutex);
auto it = g_server_ctxs.find(server_id);
if (it == g_server_ctxs.end()) {
// 修正:拼接错误信息中的 server ID
std::string err_msg = "server instance not found (ID: " + std::to_string(server_id) + ")";
sq_pushstring(v, err_msg.c_str(), -1);
return SQ_ERROR;
}
HttpServerCtx* ctx = it->second.get();
// 1. 标记停止(原子操作)
ctx->running.store(false, std::memory_order_relaxed);
// 2. 强制停止 IO 上下文(中断所有异步操作)
if (ctx->io_context) {
ctx->io_context->stop();
}
// 3. 释放 Squirrel 引用
sq_release(ctx->vm, &ctx->http_server_obj);
// 4. 移除上下文unique_ptr 自动析构)
g_server_ctxs.erase(it);
sq_pushbool(v, true);
return 1;
}
// ====================== Squirrel 绑定函数 - 发送HTTP响应 ======================
static SQInteger HttpServerResponse_Write(HSQUIRRELVM v) {
SQUserPointer P;
if (SQ_FAILED(sq_getuserpointer(v, 2, &P))) {
return sq_throwerror(v, _SC("invalid socket pointer"));
}
tcp::socket* socket = static_cast<tcp::socket*>(P);
const SQChar* Content;
if (SQ_FAILED(sq_getstring(v, 3, &Content))) {
return sq_throwerror(v, _SC("invalid response content"));
}
try {
if (socket && socket->is_open()) {
std::string response = Content;
asio::write(*socket, asio::buffer(response));
}
}
catch (const std::exception& e) {
// 清理资源
if (socket) {
asio::error_code ec;
socket->close(ec);
delete socket;
}
return sq_throwerror(v, e.what());
}
catch (...) {
if (socket) {
asio::error_code ec;
socket->close(ec);
delete socket;
}
return sq_throwerror(v, _SC("Unknown error occurred"));
}
// 最后清理socket
if (socket) {
asio::error_code ec;
socket->close(ec);
delete socket;
}
return 0;
}
// ====================== 辅助函数 - 注册Squirrel函数 ======================
static SQInteger register_Dio_func(HSQUIRRELVM v, SQFUNCTION f, const char* fname) {
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0);
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // 弹出根表
return 0;
}
// ====================== 注册所有Dio函数 ======================
static void RegisterDio(HSQUIRRELVM v) {
// 创建HTTP客户端
register_Dio_func(v, CreateHttp, _SC("Sq_CreateHttp"));
// HTTP服务器相关
register_Dio_func(v, CreateHttpServer, _SC("Sq_CreateHttpServer"));
register_Dio_func(v, StopHttpServer, _SC("Sq_StopHttpServer"));
// 发送HTTP响应
register_Dio_func(v, HttpServerResponse_Write, _SC("Sq_HttpServerResponse_Write"));
}

View File

@@ -0,0 +1,52 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <iostream>
template <typename R, typename A, typename... ARG>
R CallDungeon(A call_addr, const ARG... arguments)
{
if (!call_addr)
{
return R();
}
const auto control = reinterpret_cast<R (*)(ARG...)>(call_addr);
try
{
return control(arguments...);
}
catch (...)
{
}
return R();
}
// 获取副本编号
static SQInteger Dungeon_GetIdex(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Idx = CallDungeon<int>(0x80FDCF0, P);
sq_pushinteger(v, Idx);
return 1;
}
static SQInteger register_Dungeon_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
{
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
static void RegisterDungeon(HSQUIRRELVM v)
{
// 获取编号
register_Dungeon_func(v, Dungeon_GetIdex, _SC("Sq_Dungeon_GetIdex"));
}

1209
src/script/SqrReg_Game.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,163 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <iostream>
#include "frida-gum.h"
typedef void *(*__GetGameManagerVoid)();
static SQInteger GameManager_GameManager(HSQUIRRELVM v)
{
void *GameManager = ((__GetGameManagerVoid)0x080CC18E)();
sq_pushuserpointer(v, GameManager);
return 1;
}
typedef void *(*__GameManagerByThis)(void *GameManager);
static SQInteger GameManager_GetParty(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
void *CParty = ((__GameManagerByThis)0x08294E10)(P);
if (CParty)
sq_pushuserpointer(v, CParty);
else
sq_pushinteger(v, 0);
return 1;
}
typedef int (*cdeclCall2P)(int *a1, int a2);
static cdeclCall2P SkillSlot__get_skillslot_buf = (cdeclCall2P)0x086067DE;
static cdeclCall2P SkillSlot__gcheckComboSkillInsertQuickSlot = (cdeclCall2P)0x08608D58;
#define RDWORD(addr, offset) (*(DWORD *)((char *)(addr) + (offset)))
int __attribute__((cdecl)) hookCSkill__reform_ui_group_no(int *thisP, int *skillClassP, bool isTpSkill, int a4)
{
int p = (int)skillClassP;
if (RDWORD(skillClassP, -0x60) == 197)
{
// cout << " fix skill197 class to 4!" << endl;
*skillClassP = 4;
}
return 0;
}
int __attribute__((cdecl)) hookSkillSlot__get_skillslot_group(int *thisP, int slot)
{
// DWORD retAddr = (DWORD)gum_invocation_context_get_return_address(NULL);
// cout<< retAddr << " get_skillslot_group:" << slot << endl;
if (slot < 8 || slot >= 198)
return -1;
else if (slot >= 160)
return 4;
else if (slot >= 122)
return 3;
else if (slot >= 84)
return 2;
else if (slot >= 46)
return 1;
else
return 0;
}
int __attribute__((cdecl)) hookSkillSlot__get_skillslot_no(int *thisP, int skillId, int group, int slot, char is_active_skill)
{
if (!thisP || !*thisP)
return -1;
BYTE *buf = (BYTE *)SkillSlot__get_skillslot_buf(thisP, slot);
if (!buf)
return -1;
if (is_active_skill && SkillSlot__gcheckComboSkillInsertQuickSlot(thisP, skillId))
{
int end = skillId ? 7 : 5;
for (int i = 0; i <= end; ++i)
{
if (buf[2 * i] == skillId)
{
return i;
}
}
for (int i = 198; i <= 203; ++i)
{
if (buf[2 * i] == skillId)
{
return i;
}
}
}
int pos = 8 + group * 38;
for (int i = 0; i < 38; ++i)
{
if (buf[2 * (i + pos)] == skillId)
{
return i + pos;
}
}
return -1;
}
int __attribute__((cdecl)) hookSkillSlot__get_skillslot_no2(int *thisP, BYTE *buf, int skillId, int group, char is_active_skill)
{
if (!thisP || !*thisP || !buf)
return -1;
if (is_active_skill)
{
int end = skillId ? 7 : 5;
for (int i = 0; i <= end; ++i)
{
if (buf[2 * i] == skillId)
{
return i;
}
}
for (int i = 198; i <= 203; ++i)
{
if (buf[2 * i] == skillId)
{
return i;
}
}
}
int pos = 8 + group * 38;
for (int i = 0; i < 38; ++i)
{
if (buf[2 * (i + pos)] == skillId)
{
return i + pos;
}
}
return -1;
}
static SQInteger GameManager_FixA4Skill(HSQUIRRELVM vm)
{
GumInterceptor *v = gum_interceptor_obtain();
gum_interceptor_begin_transaction(v);
gum_interceptor_replace_fast(v, (gpointer)0x083507E8, (gpointer)hookCSkill__reform_ui_group_no, NULL);
gum_interceptor_replace_fast(v, (gpointer)0x086049FC, (gpointer)hookSkillSlot__get_skillslot_group, NULL);
gum_interceptor_replace_fast(v, (gpointer)0x08604A86, (gpointer)hookSkillSlot__get_skillslot_no, NULL);
gum_interceptor_replace_fast(v, (gpointer)0x08607DBA, (gpointer)hookSkillSlot__get_skillslot_no2, NULL);
gum_interceptor_end_transaction(v);
return 0;
}
static SQInteger register_GameManager_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
{
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
static void RegisterGameManager(HSQUIRRELVM v)
{
// 获得GameManager对象
register_GameManager_func(v, GameManager_GameManager, _SC("Sq_GameManager_GameManager"));
// 获得队伍对象
register_GameManager_func(v, GameManager_GetParty, _SC("Sq_GameManager_GetParty"));
// 修复A4技能
register_GameManager_func(v, GameManager_FixA4Skill, _SC("Sq_FixA4Skill"));
}

114
src/script/SqrReg_Inven.hpp Normal file
View File

@@ -0,0 +1,114 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <iostream>
template <typename R, typename A, typename... ARG>
R CallInven(A call_addr, const ARG... arguments)
{
if (!call_addr)
{
return R();
}
const auto control = reinterpret_cast<R (*)(ARG...)>(call_addr);
try
{
return control(arguments...);
}
catch (...)
{
}
return R();
}
// 获取背包
static SQInteger Inven_GetInven(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
void *InvenP = CallInven<void *>(0x80DA28E, P);
sq_pushuserpointer(v, InvenP);
return 1;
}
// 获取背包中的项目
static SQInteger Inven_GetItem(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Type, Slot;
sq_getinteger(v, 3, &Type);
sq_getinteger(v, 4, &Slot);
void *ItemP = CallInven<void *>(0x84FC1DE, P, Type, Slot);
sq_pushuserpointer(v, ItemP);
return 1;
}
// 删除背包中的项目
static SQInteger Inven_RemoveItem(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
CallInven<void *>(0x080CB7D8, P);
return 0;
}
// 删除背包中的指定数量的项目
static SQInteger Inven_RemoveItemFormCount(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Type, Slot, Count, Ps, Log;
sq_getinteger(v, 3, &Type);
sq_getinteger(v, 4, &Slot);
sq_getinteger(v, 5, &Count);
sq_getinteger(v, 6, &Ps);
sq_getinteger(v, 7, &Log);
SQInteger Ret = CallInven<int>(0x850400C, P, Type, Slot, Count, Ps, Log);
sq_pushinteger(v, Ret);
return 1;
}
// 根据Id获取背包中的物品槽位
static SQInteger Inven_GetItemById(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Idx;
sq_getinteger(v, 3, &Idx);
SQInteger Slot = CallInven<int>(0x08505172, P, Idx);
sq_pushinteger(v, Slot);
return 1;
}
static SQInteger register_Inven_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
{
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
static void RegisterInven(HSQUIRRELVM v)
{
// 获取背包
register_Inven_func(v, Inven_GetInven, "Sq_Inven_GetInven");
// 获取背包中的道具
register_Inven_func(v, Inven_GetItem, "Sq_Inven_GetItem");
// 删除背包中的项目
register_Inven_func(v, Inven_RemoveItem, "Sq_Inven_RemoveItem");
// 根据Id获取背包中的物品槽位
register_Inven_func(v, Inven_RemoveItemFormCount, "Sq_Inven_RemoveItemFormCount");
// 根据Id获取背包中的物品槽位
register_Inven_func(v, Inven_GetItemById, "Sq_Inven_GetItemById");
}

View File

@@ -0,0 +1,209 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include "CConnectPool.h"
#include "inline_hook.h"
#include <iostream>
#include <functional>
#include <list>
#include <ffi.h>
#include <keystone/keystone.h>
static SQInteger _file_releasehook(SQUserPointer p, SQInteger SQ_UNUSED_ARG(size))
{
free((void*)p);
return 0;
}
// 注册析构函数
static SQInteger Register_Destruction(HSQUIRRELVM v)
{
// 析构函数测试
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
sq_setinstanceup(v, 3, P);
sq_setreleasehook(v, 3, _file_releasehook);
return 0;
}
static SQInteger PointerOperation(HSQUIRRELVM v)
{
SQUserPointer Address;
sq_getuserpointer(v, 2, &Address);
SQInteger Offset;
sq_getinteger(v, 3, &Offset);
const SQChar* TypecharBuf;
sq_getstring(v, 4, &TypecharBuf);
std::string Type(TypecharBuf);
if (Type == "+")
{
sq_pushuserpointer(v, (void*)(Address + Offset));
}
else if (Type == "-")
{
sq_pushuserpointer(v, (void*)(Address - Offset));
}
return 1;
}
static SQInteger PointerOperationPointer(HSQUIRRELVM v)
{
SQUserPointer Address;
sq_getuserpointer(v, 2, &Address);
SQUserPointer Address2;
sq_getuserpointer(v, 3, &Address2);
const SQChar* TypecharBuf;
sq_getstring(v, 4, &TypecharBuf);
std::string Type(TypecharBuf);
if (Type == "+")
{
sq_pushuserpointer(v, (void*)((int)Address + (int)Address2));
}
else if (Type == "-")
{
sq_pushuserpointer(v, (void*)((int)Address - (int)Address2));
}
return 1;
}
// 写字节数组
static SQInteger Memory_WriteByteArr(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
char* Address = (char*)P;
size_t Idx = 0;
sq_pushnull(v); // null iterator
while (SQ_SUCCEEDED(sq_next(v, 3)))
{
SQInteger Buf;
sq_getinteger(v, -1, &Buf);
CMem::WriteUChar((Address + Idx), Buf);
// 这里-1是值-2是键
sq_pop(v, 2); // 在下一次迭代之前弹出键和值
Idx++;
}
sq_pop(v, 1);
return 0;
}
static SQInteger Memory_WriteBlob(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQUserPointer blob_data;
SQInteger blob_len = sqstd_getblobsize(v, 3);
sqstd_getblob(v, 3, &blob_data);
CMem::WriteBytes(P, blob_data, blob_len);
return 0;
}
// 读内存字符串
static SQInteger Memory_ReadString(HSQUIRRELVM v)
{
// 内存地址
SQUserPointer Address;
// 获取地址
sq_getuserpointer(v, 2, &Address);
if (sq_gettop(v) == 3)
{
SQInteger Length;
sq_getinteger(v, 3, &Length);
sq_pushstring(v, (char*)(Address), Length);
}
else
{
sq_pushstring(v, (char*)(Address), -1);
}
return 1;
}
// 将汇编代码字符串转为字节码
static SQInteger Asmjit_Compile(HSQUIRRELVM v)
{
const SQChar* CharBuf;
sq_getstring(v, 2, &CharBuf);
std::string AsmCode(CharBuf);
SQUserPointer Address = 0;
if (sq_gettop(v) == 3)
{
sq_getuserpointer(v, 3, &Address);
}
ks_engine* ks;
ks_err err;
size_t count;
unsigned char* encode;
size_t size;
// 打开Keystone引擎使用x86-64架构和Intel语法
if (ks_open(KS_ARCH_X86, KS_MODE_32, &ks) != KS_ERR_OK)
{
// fprintf(stderr, "Failed to open Keystone\n");
return -1;
}
// 可选设置语法为Intel默认已经是Intel可省略
ks_option(ks, KS_OPT_SYNTAX, KS_OPT_SYNTAX_INTEL);
// 汇编指令
if (ks_asm(ks, AsmCode.c_str(), (uint64_t)Address, &encode, &size, &count) != KS_ERR_OK)
{
// fprintf(stderr, "Assembly error: %s\n", ks_strerror(ks_errno(ks)));
ks_close(ks);
return -1;
}
// 创建Squirrel数组
sq_newarray(v, 0);
// 将每个字节压入数组
for (size_t i = 0; i < size; ++i)
{
sq_pushinteger(v, encode[i]); // 压入字节值
sq_arrayappend(v, -2); // 添加到数组(-2是数组位置
}
// 释放资源
ks_free(encode);
ks_close(ks);
return 1; // 返回1表示有返回值
}
static SQInteger register_Memory_func(HSQUIRRELVM v, SQFUNCTION f, const char* fname)
{
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
static void RegisterMemory(HSQUIRRELVM v)
{
// 析构函数
register_Memory_func(v, Register_Destruction, "Register_Destruction");
// 运算
register_Memory_func(v, PointerOperation, "Sq_PointerOperation");
register_Memory_func(v, PointerOperationPointer, "Sq_PointerOperationPointer");
// 写字节
register_Memory_func(v, Memory_WriteByteArr, "Sq_Memory_WriteByteArr");
// 读字符串
register_Memory_func(v, Memory_ReadString, "Sq_Memory_ReadString");
// 将汇编代码字符串转为字节码
register_Memory_func(v, Asmjit_Compile, "Sq_Asmjit_Compile");
// 写
register_Memory_func(v, Memory_WriteBlob, "Sq_Memory_WriteBlob");
}

View File

@@ -0,0 +1,139 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include "import.h"
#include "inline_hook.h"
#include "Singleton.h"
#include "./sdk/sdk_class.h"
#include "utils.h"
#include "GameDataManager.h"
#include "PacketBuf.h"
#include "User.h"
#include <iostream>
static SQInteger Packet_New(HSQUIRRELVM v)
{
InterfacePacketBuf *Pck = (InterfacePacketBuf *)PacketGuard::NewPacketGuard();
sq_pushuserpointer(v, Pck);
return 1;
}
static SQInteger Packet_Put_header(HSQUIRRELVM v)
{
SQUserPointer Buf;
sq_getuserpointer(v, 2, &Buf);
InterfacePacketBuf *Pck = (InterfacePacketBuf *)Buf;
SQInteger Header1;
sq_getinteger(v, 3, &Header1);
SQInteger Header2;
sq_getinteger(v, 4, &Header2);
Pck->put_header(Header1, Header2);
return 0;
}
static SQInteger Packet_Put_byte(HSQUIRRELVM v)
{
SQUserPointer Buf;
sq_getuserpointer(v, 2, &Buf);
InterfacePacketBuf *Pck = (InterfacePacketBuf *)Buf;
SQInteger Byte;
sq_getinteger(v, 3, &Byte);
Pck->put_byte(Byte);
return 0;
}
static SQInteger Packet_Put_short(HSQUIRRELVM v)
{
SQUserPointer Buf;
sq_getuserpointer(v, 2, &Buf);
InterfacePacketBuf *Pck = (InterfacePacketBuf *)Buf;
SQInteger Short;
sq_getinteger(v, 3, &Short);
Pck->put_short(Short);
return 0;
}
static SQInteger Packet_Put_int(HSQUIRRELVM v)
{
SQUserPointer Buf;
sq_getuserpointer(v, 2, &Buf);
InterfacePacketBuf *Pck = (InterfacePacketBuf *)Buf;
SQInteger Int;
sq_getinteger(v, 3, &Int);
Pck->put_int(Int);
return 0;
}
static SQInteger Packet_Put_binary(HSQUIRRELVM v)
{
SQUserPointer Buf;
sq_getuserpointer(v, 2, &Buf);
InterfacePacketBuf *Pck = (InterfacePacketBuf *)Buf;
const SQChar *Str;
sq_getstring(v, 3, &Str);
Pck->put_str((char *)Str, strlen(Str));
return 0;
}
static SQInteger Packet_Put_binaryex(HSQUIRRELVM v)
{
SQUserPointer Buf;
sq_getuserpointer(v, 2, &Buf);
InterfacePacketBuf *Pck = (InterfacePacketBuf *)Buf;
SQUserPointer Str;
sq_getuserpointer(v, 3, &Str);
SQInteger Len;
sq_getinteger(v, 4, &Len);
Pck->put_binary((char *)Str, Len);
return 0;
}
static SQInteger Packet_Finalize(HSQUIRRELVM v)
{
SQUserPointer Buf;
sq_getuserpointer(v, 2, &Buf);
InterfacePacketBuf *Pck = (InterfacePacketBuf *)Buf;
SQBool B;
sq_getbool(v, 3, &B);
Pck->finalize(B);
return 0;
}
static SQInteger Packet_Send(HSQUIRRELVM v)
{
SQUserPointer userbuf;
sq_getuserpointer(v, 2, &userbuf);
CUser *user = (CUser *)userbuf;
SQUserPointer Buf;
sq_getuserpointer(v, 3, &Buf);
user->Send((PacketGuard *)Buf);
return 0;
}
static SQInteger Packet_Delete(HSQUIRRELVM v)
{
SQUserPointer Buf;
sq_getuserpointer(v, 2, &Buf);
InterfacePacketBuf *Pck = (InterfacePacketBuf *)Buf;
InterfacePacketBuf::DelPacketBuf(Pck);
return 0;
}
static SQInteger register_Packet_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
{
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
static void RegisterPacket(HSQUIRRELVM v)
{
register_Packet_func(v, Packet_New, _SC("Sq_Packet_New"));
register_Packet_func(v, Packet_Put_header, _SC("Sq_Packet_Put_header"));
register_Packet_func(v, Packet_Put_byte, _SC("Sq_Packet_Put_byte"));
register_Packet_func(v, Packet_Put_short, _SC("Sq_Packet_Put_short"));
register_Packet_func(v, Packet_Put_int, _SC("Sq_Packet_Put_int"));
register_Packet_func(v, Packet_Put_binary, _SC("Sq_Packet_Put_binary"));
register_Packet_func(v, Packet_Put_binaryex, _SC("Sq_Packet_Put_binaryex"));
register_Packet_func(v, Packet_Finalize, _SC("Sq_Packet_Finalize"));
register_Packet_func(v, Packet_Send, _SC("Sq_Packet_Send"));
register_Packet_func(v, Packet_Delete, _SC("Sq_Packet_Delete"));
}

View File

@@ -0,0 +1,95 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <iostream>
template <typename R, typename A, typename... ARG>
R CallParty(A call_addr, const ARG... arguments)
{
if (!call_addr)
{
return R();
}
const auto control = reinterpret_cast<R (*)(ARG...)>(call_addr);
try
{
return control(arguments...);
}
catch (...)
{
}
return R();
}
typedef int (*__CreateParty)(void *CParty, void *CUser);
static SQInteger Party_CreateParty(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQUserPointer User;
sq_getuserpointer(v, 3, &User);
((__CreateParty)0x0859B1BE)(P, User);
return 0;
}
typedef int (*__SetPartyInfoUI)(void *CParty, int code);
static SQInteger Party_SetPartyInfoUI(HSQUIRRELVM v) // 设置队伍信息UI可以不写 创出来空的 要写的话要搞个指针 写入很多参数
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
((__SetPartyInfoUI)0x0859B234)(P, 0x44d672e);
return 0;
}
typedef int (*__JoinParty)(void *CParty, void *CUser);
static SQInteger Party_JoinParty(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQUserPointer User;
sq_getuserpointer(v, 3, &User);
((__JoinParty)0x0859B2B6)(P, User);
return 0;
}
typedef int (*__SendPartyIpInfo)(void *CParty);
static SQInteger Party_SendPartyIpInfo(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
((__SendPartyIpInfo)0x0859CEA2)(P);
return 0;
}
// 获取战斗对象
static SQInteger Party_GetBattle_Field(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
sq_pushuserpointer(v, P + 2852);
return 1;
}
static SQInteger register_Party_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
{
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
static void RegisterParty(HSQUIRRELVM v)
{
// 创建队伍
register_Party_func(v, Party_CreateParty, _SC("Sq_Party_CreateParty"));
// 设置队伍信息UI
register_Party_func(v, Party_SetPartyInfoUI, _SC("Sq_Party_SetPartyInfoUI"));
// 让玩家加入队伍
register_Party_func(v, Party_JoinParty, _SC("Sq_Party_JoinParty"));
// 广播队伍玩家IP
register_Party_func(v, Party_SendPartyIpInfo, _SC("Sq_Party_SendPartyIpInfo"));
// 获取副本编号
register_Party_func(v, Party_GetBattle_Field, _SC("Sq_Party_GetBattle_Field"));
}

247
src/script/SqrReg_RSA.hpp Normal file
View File

@@ -0,0 +1,247 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <iostream>
#include <fstream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
// 错误信息打印函数
void print_openssl_error() {
char err_buf[256];
ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf));
std::cerr << "OpenSSL 错误: " << err_buf << std::endl;
}
// 生成 RSA 密钥对并保存到文件
// 生成 RSA 密钥对公钥X.509/PKCS#8 格式私钥PKCS#1 格式)
bool generate_rsa_key(const std::string& pub_key_path,
const std::string& pri_key_path,
int key_bits = 2048) {
// 1. 创建 RSA 对象并生成密钥对
RSA* rsa = RSA_new();
BIGNUM* bn = BN_new();
if (!rsa || !bn) {
std::cerr << "创建 RSA/BIGNUM 失败" << std::endl;
RSA_free(rsa);
BN_free(bn);
return false;
}
// 设置公钥指数65537
if (BN_set_word(bn, RSA_F4) != 1) {
std::cerr << "设置 BIGNUM 失败" << std::endl;
print_openssl_error();
RSA_free(rsa);
BN_free(bn);
return false;
}
// 生成 RSA 密钥对
if (RSA_generate_key_ex(rsa, key_bits, bn, nullptr) != 1) {
std::cerr << "生成 RSA 密钥对失败" << std::endl;
print_openssl_error();
RSA_free(rsa);
BN_free(bn);
return false;
}
// 2. 封装 RSA 到 EVP_PKEY用于生成 X.509/PKCS#8 公钥)
EVP_PKEY* evp_key = EVP_PKEY_new();
if (!evp_key || EVP_PKEY_assign_RSA(evp_key, rsa) != 1) {
std::cerr << "封装 EVP_PKEY 失败" << std::endl;
print_openssl_error();
EVP_PKEY_free(evp_key);
RSA_free(rsa);
BN_free(bn);
return false;
}
// 3. 保存 X.509/PKCS#8 格式公钥(-----BEGIN PUBLIC KEY-----
FILE* pub_file = fopen(pub_key_path.c_str(), "w");
if (!pub_file) {
std::cerr << "打开公钥文件失败: " << pub_key_path << std::endl;
EVP_PKEY_free(evp_key);
BN_free(bn);
return false;
}
if (PEM_write_PUBKEY(pub_file, evp_key) != 1) {
std::cerr << "写入 X.509 公钥失败" << std::endl;
print_openssl_error();
fclose(pub_file);
EVP_PKEY_free(evp_key);
BN_free(bn);
return false;
}
fclose(pub_file);
// 4. 保存 PKCS#1 格式私钥(-----BEGIN RSA PRIVATE KEY-----
FILE* pri_file = fopen(pri_key_path.c_str(), "w");
if (!pri_file) {
std::cerr << "打开私钥文件失败: " << pri_key_path << std::endl;
EVP_PKEY_free(evp_key);
BN_free(bn);
return false;
}
if (PEM_write_RSAPrivateKey(pri_file, rsa, nullptr, nullptr, 0, nullptr, nullptr) != 1) {
std::cerr << "写入私钥失败" << std::endl;
print_openssl_error();
fclose(pri_file);
EVP_PKEY_free(evp_key);
BN_free(bn);
return false;
}
fclose(pri_file);
// 5. 释放资源EVP_PKEY_free 会自动释放内部的 RSA 对象)
EVP_PKEY_free(evp_key);
BN_free(bn);
std::cout << "RSA 密钥生成成功!" << std::endl;
std::cout << "公钥X.509/PKCS#8 格式): " << pub_key_path << std::endl;
std::cout << "私钥PKCS#1 格式): " << pri_key_path << std::endl;
return true;
}
static SQInteger Rsa_GenerateKey(HSQUIRRELVM v)
{
// 初始化 OpenSSL 错误处理
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
// 生成 2048 位 RSA 密钥对(推荐使用 2048/4096 位)
bool ret = generate_rsa_key("public.pem", "private.pem", 2048);
// 清理 OpenSSL 资源
EVP_cleanup();
ERR_free_strings();
return 0;
}
// 从文件加载私钥PKCS#1 格式)
RSA* load_rsa_private_key(const std::string& pri_key_path) {
FILE* pri_file = fopen(pri_key_path.c_str(), "r");
if (!pri_file) {
std::cerr << "打开私钥文件失败: " << pri_key_path << std::endl;
return nullptr;
}
// 加载 PKCS#1 格式私钥
RSA* rsa = PEM_read_RSAPrivateKey(pri_file, nullptr, nullptr, nullptr);
fclose(pri_file);
if (!rsa) {
std::cerr << "加载私钥失败" << std::endl;
print_openssl_error();
}
return rsa;
}
// 新增:十六进制字符串转字节数组(核心补全)
bool hex_string_to_bytes(const std::string& hex_str, std::vector<unsigned char>& bytes) {
bytes.clear();
// 检查长度是否为偶数十六进制字符串必须2字符=1字节
if (hex_str.length() % 2 != 0) {
std::cerr << "十六进制字符串长度为奇数,无效" << std::endl;
return false;
}
for (size_t i = 0; i < hex_str.length(); i += 2) {
std::string byte_str = hex_str.substr(i, 2);
// 十六进制转字节处理0-9/a-f/A-F
unsigned char byte = static_cast<unsigned char>(strtol(byte_str.c_str(), nullptr, 16));
bytes.push_back(byte);
}
return true;
}
bool rsa_private_encrypt(const std::vector<unsigned char>& plaintext_bytes, RSA* rsa_pri, std::string& ciphertext) {
if (!rsa_pri || plaintext_bytes.empty()) return false;
int rsa_len = RSA_size(rsa_pri);
unsigned char* enc_buf = new unsigned char[rsa_len];
// 加密字节数组而非字符串的ASCII
int enc_len = RSA_private_encrypt(
plaintext_bytes.size(), // 明文长度(字节数)
plaintext_bytes.data(), // 明文字节数组
enc_buf, // 加密结果缓冲区
rsa_pri, // RSA私钥
RSA_PKCS1_PADDING // 填充方式和Java一致
);
if (enc_len > 0) {
ciphertext = std::string((char*)enc_buf, enc_len);
} else {
std::cerr << "私钥加密失败2048位RSA最多加密245字节" << std::endl;
print_openssl_error();
}
delete[] enc_buf;
return enc_len > 0;
}
static SQInteger Rsa_Private_Encrypt(HSQUIRRELVM v)
{
const SQChar* hex_str;
sq_getstring(v, 2, &hex_str); // 获取Squirrel传入的十六进制字符串
// 1. 加载RSA私钥
RSA* rsa_pri = load_rsa_private_key("privatekey.pem");
if (!rsa_pri) {
sq_pushnull(v);
return 1;
}
// 2. 核心十六进制字符串转字节数组对齐Java的toByteArray
std::vector<unsigned char> plaintext_bytes;
if (!hex_string_to_bytes(std::string(hex_str), plaintext_bytes)) {
RSA_free(rsa_pri);
sq_pushnull(v);
return 1;
}
// 3. 加密字节数组
std::string ciphertext;
bool success = rsa_private_encrypt(plaintext_bytes, rsa_pri, ciphertext);
// 4. 返回加密后的字节串Squirrel中以字符串形式承载二进制数据
if (success) {
sq_pushstring(v, ciphertext.c_str(), ciphertext.length());
} else {
sq_pushnull(v);
}
// 释放资源
RSA_free(rsa_pri);
return 1;
}
// ====================== 辅助函数 - 注册Squirrel函数 ======================
static SQInteger register_Rsa_func(HSQUIRRELVM v, SQFUNCTION f, const char* fname) {
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0);
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // 弹出根表
return 0;
}
// ====================== 注册所有Dio函数 ======================
static void RegisterRsa(HSQUIRRELVM v) {
register_Rsa_func(v, Rsa_GenerateKey, _SC("Sq_Rsa_GenerateKey"));
//使用私钥签名
register_Rsa_func(v, Rsa_Private_Encrypt, _SC("Sq_Rsa_Private_Encrypt"));
}

543
src/script/SqrReg_User.hpp Normal file
View File

@@ -0,0 +1,543 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <vector>
#include <cstring>
#include <iostream>
template <typename R, typename A, typename... ARG>
R CallUser(A call_addr, const ARG... arguments)
{
if (!call_addr)
{
return R();
}
const auto control = reinterpret_cast<R (*)(ARG...)>(call_addr);
try
{
return control(arguments...);
}
catch (...)
{
}
return R();
}
typedef int (*__GetUserByThis)(void *CUser);
typedef int (*__GetUserArea)(void *CUser, bool a);
typedef int (*__SetUserByInt)(void *CUser, int Value);
static SQInteger CUser_GetPosX(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger X = int(((__GetUserByThis)0x0813492c)((void *)P));
sq_pushinteger(v, X);
return 1;
}
static SQInteger CUser_GetPosY(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Y = int(((__GetUserByThis)0x0813493c)((void *)P));
sq_pushinteger(v, Y);
return 1;
}
static SQInteger CUser_Direction(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x0813494c)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_GetVill(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Vill = int(((__GetUserByThis)0x08645564)((void *)P));
sq_pushinteger(v, Vill);
return 1;
}
static SQInteger CUser_GetArea(HSQUIRRELVM v)
{
SQUserPointer P;
SQInteger Type = 0;
sq_getuserpointer(v, 2, &P);
if (sq_gettop(v) == 3)
{
sq_getinteger(v, 3, &Type);
}
SQInteger Area = int(((__GetUserArea)0x086813BE)((void *)P, Type));
sq_pushinteger(v, Area);
return 1;
}
static SQInteger CUser_GetState(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger State = int(((__GetUserByThis)0x080DA38C)((void *)P));
sq_pushinteger(v, State);
return 1;
}
static SQInteger CUser_GetCharacCount(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Count = int(((__GetUserByThis)0x082300E8)((void *)P));
sq_pushinteger(v, Count);
return 1;
}
static SQInteger CUser_GetUniqueId(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger UID = int(((__GetUserByThis)0x080DA37C)((void *)P));
sq_pushinteger(v, UID);
return 1;
}
static SQInteger CUser_GetAccId(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger UID = int(((__GetUserByThis)0x080DA36E)((void *)P));
sq_pushinteger(v, UID);
return 1;
}
static SQInteger CUser_GetCharacNo(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger CID = int(((__GetUserByThis)0x080CBC4E)((void *)P));
sq_pushinteger(v, CID);
return 1;
}
static SQInteger CUser_GetCharacJob(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x080FDF20)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_GetCharacName(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x08101028)((void *)P));
sq_pushstring(v, _SC((char *)Ret), -1);
return 1;
}
static SQInteger CUser_GetCharacLevel(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x080DA2B8)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_SetCharacLevel(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Value;
sq_getinteger(v, 3, &Value);
char *a = new char[4];
CallUser<int>(0x822FC8E, a, P, Value);
return 0;
}
static SQInteger CUser_GetCharacGrowType(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x0815741C)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_GetCharacSecondGrowType(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x0822F23C)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_GetFatigue(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x08657766)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_GetMaxFatigue(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x08657804)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
typedef int (*__CUser_DisConnSig)(void *CUser, int type, int is, int err);
static SQInteger CUser_DisConnSig(HSQUIRRELVM v)
{
SQUserPointer P;
SQInteger Src;
SQInteger P2;
SQInteger P3;
sq_getuserpointer(v, 2, &P);
sq_getinteger(v, 3, &Src);
sq_getinteger(v, 4, &P2);
sq_getinteger(v, 5, &P3);
SQInteger Ret = int(((__CUser_DisConnSig)0x086489F4)((void *)P, Src, P2, P3));
sq_pushinteger(v, Ret);
return 1;
}
typedef void *(*__GetUserParty)(void *CUser);
static SQInteger CUser_GetParty(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQUserPointer Ret = (((__GetUserParty)0x0865514C)((void *)P));
sq_pushuserpointer(v, Ret);
return 1;
}
static SQInteger CUser_CheckInBossTower(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x082a67e2)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_CheckInBlueMarble(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x080da32a)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_IsGmMode(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x0814589c)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_GetVisibleValues(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x0868BDE4)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
static SQInteger CUser_GetCurCharacLastPlayTick(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Ret = int(((__GetUserByThis)0x082A66AA)((void *)P));
sq_pushinteger(v, Ret);
return 1;
}
typedef int (*__GiveUserItem)(void *CUser, int a2, int a3, int a4, int *a5, int a6);
typedef int (*__UserSendUpdateItemList)(void *CUser, int a2, int a3, int a4);
static SQInteger CUser_GiveUserItem(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger ItemId, ItemCount;
sq_getinteger(v, 3, &ItemId);
sq_getinteger(v, 4, &ItemCount);
int *ItemSpace = (int *)malloc(4);
int Slot = int(((__GiveUserItem)0x0867B6D4)((void *)P, ItemId, ItemCount, 6, ItemSpace, 0));
if (Slot >= 0)
{
sq_newarray(v, 0);
sq_pushinteger(v, *ItemSpace);
sq_arrayappend(v, -2);
sq_pushinteger(v, Slot);
sq_arrayappend(v, -2);
}
else
sq_pushnull(v);
return 1;
}
// 通知客户端更新道具信息
static SQInteger CUser_SendUpdateItemList(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Type, ItemSpace, Slot;
sq_getinteger(v, 3, &Type);
sq_getinteger(v, 4, &ItemSpace);
sq_getinteger(v, 5, &Slot);
CallUser<int>(0x867C65A, P, Type, ItemSpace, Slot);
return 0;
}
// 通知客户端更新背包栏
static SQInteger CUser_SendItemSpace(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger itemSpace;
sq_getinteger(v, 3, &itemSpace);
// std::cout << *(int *)P << std::endl;
CallUser<int>(0x865DB6C, P, itemSpace);
return 0;
}
// 发送邮件
static SQInteger CUser_SendMail(HSQUIRRELVM v)
{
SQInteger Cid;
sq_getinteger(v, 2, &Cid);
std::vector<std::pair<int, int>> List;
List.clear();
int ItemListLen = 0;
sq_pushnull(v); // null iterator
while (SQ_SUCCEEDED(sq_next(v, 3)))
{
SQInteger Index, Count;
sq_getinteger(v, -1, &Count);
sq_getinteger(v, -2, &Index);
std::pair<int, int> pair1 = std::make_pair(Index, Count);
List.push_back(pair1);
// 这里-1是值-2是键
sq_pop(v, 2); // 在下一次迭代之前弹出键和值
ItemListLen++;
}
sq_pop(v, 1);
void *addition_slots = malloc(1000);
for (int i = 0; i < 10; i++)
{
CallUser<void>(0x80CB854, addition_slots + (i * 61));
}
CallUser<int>(0x8556A14, List, addition_slots, 10);
SQInteger Gold;
sq_getinteger(v, 4, &Gold);
const SQChar *Title;
const SQChar *Text;
sq_getstring(v, 5, &Title);
sq_getstring(v, 6, &Text);
int TextLen = strlen(Text);
CallUser<int>(0x8556B68, Title, addition_slots, ItemListLen, Gold, Cid, Text, TextLen, 0, 99, 1);
return 0;
}
// 发送邮件
static SQInteger CUser_ChangeGrowType(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Base, Ex;
sq_getinteger(v, 3, &Base);
sq_getinteger(v, 4, &Ex);
CallUser<int>(0x867B048, P, Base, Ex);
return 0;
}
// 发送消息包
static SQInteger CUser_SendNotiPacket(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Type1, Type2, Type3;
sq_getinteger(v, 3, &Type1);
sq_getinteger(v, 4, &Type2);
sq_getinteger(v, 5, &Type3);
CallUser<int>(0x867BA5C, P, Type1, Type2, Type3);
return 0;
}
// 获取技能树
static SQInteger CUser_GetSkillW(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
void *S = CallUser<void *>(0x822F140, P);
sq_pushuserpointer(v, S);
return 1;
}
// 重置技能
static SQInteger CUser_InitSkillW(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger GrowType, IsAwa;
sq_getinteger(v, 3, &GrowType);
sq_getinteger(v, 4, &IsAwa);
CallUser<int>(0x8608120, P, GrowType, IsAwa);
return 0;
}
// 改变GM完成任务模式
static SQInteger CUser_ChangeGmQuestFlag(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Type;
sq_getinteger(v, 3, &Type);
CallUser<int>(0x822FC8E, P, Type);
return 0;
}
// 任务相关操作
static SQInteger CUser_QuestAction(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Type, QuestId, Reward, Flag;
sq_getinteger(v, 3, &Type);
sq_getinteger(v, 4, &QuestId);
sq_getinteger(v, 5, &Reward);
sq_getinteger(v, 6, &Flag);
CallUser<int>(0x0866DA8A, P, Type, QuestId, Reward, Flag);
return 0;
}
// 刷新上次任务完成时间
static SQInteger CUser_RefreshLastQuestTime(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
*(int *)((void *)P + 0x79644) = 0;
return 0;
}
// 充值点券
static SQInteger CUser_RechargeCoupons(HSQUIRRELVM v)
{
SQUserPointer User;
sq_getuserpointer(v, 2, &User);
SQInteger Amount;
sq_getinteger(v, 3, &Amount);
CallUser<int>(0x80FFCA4, *(uintptr_t *)0x941F734, User, 5, Amount, (void *)0x8C7FA20, (void *)0x8C7FA20, "Gm", (void *)0, (void *)0, (void *)0);
CallUser<int>(0x8100790, *(uintptr_t *)0x941F734, User);
return 0;
}
// 充值代币券
static SQInteger CUser_RechargeCouponsPoint(HSQUIRRELVM v)
{
SQUserPointer User;
sq_getuserpointer(v, 2, &User);
SQInteger Amount;
sq_getinteger(v, 3, &Amount);
CallUser<int>(0x80FFFC0, *(uintptr_t *)0x941F734, User, Amount, 4, (void *)0, (void *)0);
CallUser<int>(0x8100790, *(uintptr_t *)0x941F734, User);
return 0;
}
// 充值金币
static SQInteger CUser_RechargeMoney(HSQUIRRELVM v)
{
SQUserPointer User;
sq_getuserpointer(v, 2, &User);
SQInteger Amount;
sq_getinteger(v, 3, &Amount);
CallUser<int>(0x84FF29C, User, Amount, 0, 0, 0);
return 0;
}
static SQInteger register_User_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
{
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
static void RegisterUser(HSQUIRRELVM v)
{
// 获取X坐标
register_User_func(v, CUser_GetPosX, "Sq_CUser_GetPosX");
// 获取Y坐标
register_User_func(v, CUser_GetPosY, "Sq_CUser_GetPosY");
// 获取朝向
register_User_func(v, CUser_Direction, "Sq_CUser_Direction");
// 获取城镇编号
register_User_func(v, CUser_GetVill, "Sq_CUser_GetTownIndex");
// 获取区域编号
register_User_func(v, CUser_GetArea, "Sq_CUser_GetAreaIndex");
// 获取账号状态
register_User_func(v, CUser_GetState, "Sq_CUser_GetState");
// 获取角色数量
register_User_func(v, CUser_GetCharacCount, "Sq_CUser_GetCharacCount");
// 获取UID
register_User_func(v, CUser_GetAccId, "Sq_CUser_GetAccId");
// 获取UniqueId
register_User_func(v, CUser_GetUniqueId, "Sq_CUser_GetUniqueId");
// 获取CID
register_User_func(v, CUser_GetCharacNo, "Sq_CUser_GetCharacNo");
// 获取角色职业
register_User_func(v, CUser_GetCharacJob, "Sq_CUser_GetCharacJob");
// 获取角色名称
register_User_func(v, CUser_GetCharacName, "Sq_CUser_GetCharacName");
// 获取角色等级
register_User_func(v, CUser_GetCharacLevel, "Sq_CUser_GetCharacLevel");
// 设置角色等级
register_User_func(v, CUser_SetCharacLevel, "Sq_CUser_SetCharacLevel");
// 获取角色转职职业
register_User_func(v, CUser_GetCharacGrowType, "Sq_CUser_GetCharacGrowType");
// 获取角色觉醒职业
register_User_func(v, CUser_GetCharacSecondGrowType, "Sq_CUser_GetCharacSecondGrowType");
// 获取已用疲劳值
register_User_func(v, CUser_GetFatigue, "Sq_CUser_GetFatigue");
// 获取最大疲劳值
register_User_func(v, CUser_GetMaxFatigue, "Sq_CUser_GetMaxFatigue");
// 踢人
register_User_func(v, CUser_DisConnSig, "Sq_CUser_DisConnSig");
// 获取当前小队/副本
register_User_func(v, CUser_GetParty, "Sq_CUser_GetParty");
// 获是否在领主塔
register_User_func(v, CUser_CheckInBossTower, "Sq_CUser_CheckInBossTower");
// 获取是否在龙之路
register_User_func(v, CUser_CheckInBlueMarble, "Sq_CUser_CheckInBlueMarble");
// 是否开启GM权限
register_User_func(v, CUser_IsGmMode, "Sq_CUser_IsGmMode");
// 获取可见Values
register_User_func(v, CUser_GetVisibleValues, "Sq_CUser_GetVisibleValues");
// 获取账号上次退出游戏的时间
register_User_func(v, CUser_GetCurCharacLastPlayTick, "Sq_CUser_GetCurCharacLastPlayTick");
// 发送道具
register_User_func(v, CUser_GiveUserItem, "Sq_CUser_GiveUserItem");
// 通知客户端更新背包
register_User_func(v, CUser_SendItemSpace, "Sq_CUser_SendItemSpace");
// 通知客户端道具更新
register_User_func(v, CUser_SendUpdateItemList, "Sq_CUser_SendUpdateItemList");
// 发送GM邮件
register_User_func(v, CUser_SendMail, "Sq_CUser_SendMail");
// 更改职业
register_User_func(v, CUser_ChangeGrowType, "Sq_CUser_ChangeGrowType");
// 发送消息包
register_User_func(v, CUser_SendNotiPacket, "Sq_CUser_SendNotiPacket");
// 获取技能树
register_User_func(v, CUser_GetSkillW, "Sq_CUser_GetSkillW");
// 重置技能树
register_User_func(v, CUser_InitSkillW, "Sq_CUser_InitSkillW");
// 改变GM完成任务模式
register_User_func(v, CUser_ChangeGmQuestFlag, "Sq_CUser_ChangeGmQuestFlag");
// 任务相关操作
register_User_func(v, CUser_QuestAction, "Sq_CUser_QuestAction");
// 刷新上次任务完成时间
register_User_func(v, CUser_RefreshLastQuestTime, "Sq_CUser_RefreshLastQuestTime");
// 充值点券
register_User_func(v, CUser_RechargeCoupons, "Sq_CUser_RechargeCoupons");
// 充值代币券
register_User_func(v, CUser_RechargeCouponsPoint, "Sq_CUser_RechargeCouponsPoint");
// 充值金币
register_User_func(v, CUser_RechargeMoney, "Sq_CUser_RechargeMoney");
}

177
src/script/SqrReg_World.hpp Normal file
View File

@@ -0,0 +1,177 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <iostream>
#include <map>
typedef void *(*__G_GameWorld)();
static SQInteger Get_GameWorld(HSQUIRRELVM v)
{
void *World = ((__G_GameWorld)0x080DA3A7)();
sq_pushuserpointer(v, World);
return 1;
}
typedef int (*__GetSessionByUid)(void *World, int Uid);
static SQInteger GameWorld_GetSessionByUid(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Uid;
sq_getinteger(v, 3, &Uid);
SQInteger Session = ((__GetSessionByUid)0x086C4C24)((void *)P, Uid);
sq_pushinteger(v, Session);
return 1;
}
typedef void *(*__GetUserBySession)(void *World, int Session);
static SQInteger GameWorld_GetUserBySession(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Session;
sq_getinteger(v, 3, &Session);
void *User = ((__GetUserBySession)0x086C4B9C)((void *)P, Session);
sq_pushuserpointer(v, User);
return 1;
}
typedef void *(*__GetUserByUid)(void *World, int Uid);
static SQInteger GameWorld_GetUserByUid(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Uid;
sq_getinteger(v, 3, &Uid);
void *User = ((__GetUserByUid)0x086C4D40)((void *)P, Uid);
sq_pushuserpointer(v, User);
return 1;
}
typedef void *(*__GetUserByName)(void *World, char *Name);
static SQInteger GameWorld_GetUserByName(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
const SQChar *Name;
sq_getstring(v, 3, &Name);
void *User = ((__GetUserByName)0x086C9464)((void *)P, (char *)Name);
sq_pushuserpointer(v, User);
return 1;
}
typedef int (*__GetUserCount)(void *World);
static SQInteger GameWorld_GetUserCount(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQInteger Count = ((__GetUserCount)0x086C4550)((void *)P);
sq_pushinteger(v, Count);
return 1;
}
typedef void (*__SendAll)(void *World, void *Pack);
static SQInteger GameWorld_SendAll(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQUserPointer Pck;
sq_getuserpointer(v, 3, &Pck);
((__SendAll)0x086C8C14)((void *)P, (void *)Pck);
return 0;
}
typedef void (*__SendPartyInfoToAll)(void *World, void *CParty, int code);
static SQInteger GameWorld_SendPartyInfoToAll(HSQUIRRELVM v)
{
SQUserPointer World;
sq_getuserpointer(v, 2, &World);
SQUserPointer CParty;
sq_getuserpointer(v, 3, &CParty);
((__SendPartyInfoToAll)0x086C878A)((void *)World, (void *)CParty, 0);
return 0;
}
// typedef std::map<int, std::string> (*__GetUserIdList)(&std::vector<unsigned short> a1, int a2);
// static SQInteger GetUserIdList(HSQUIRRELVM v)
// {
// SQInteger a1, a2;
// sq_getinteger(v, 2, &a1);
// sq_getinteger(v, 3, &a2);
// std::vector<unsigned short> Qs;
// std::map<int, std::string> Ret = ((__GetUserIdList)0x086C305E)(&Qs, a2);
// std::cout << Qs.size() << std::endl;
// std::cout << Ret.size() << std::endl;
// return 0;
// }
typedef void *(*__WorldMoveArea)(void *World, void *User, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11);
static SQInteger GameWorld_MoveArea(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQUserPointer Player;
sq_getuserpointer(v, 3, &Player);
SQInteger TownIndex, AreaIndex, Xpos, Ypos;
sq_getinteger(v, 4, &TownIndex);
sq_getinteger(v, 5, &AreaIndex);
sq_getinteger(v, 6, &Xpos);
sq_getinteger(v, 7, &Ypos);
((__WorldMoveArea)0x86C5A84)((void *)P, (void *)Player, TownIndex, AreaIndex, Xpos, Ypos, 0, 0, 0, 0, 0);
return 0;
}
typedef void *(*__SendDungeonInOut)(void *World, void *User, int a3, bool a4);
static SQInteger GameWorld_SendDungeonInOut(HSQUIRRELVM v)
{
SQUserPointer P;
sq_getuserpointer(v, 2, &P);
SQUserPointer Player;
sq_getuserpointer(v, 3, &Player);
SQInteger Index;
SQBool Model;
sq_getinteger(v, 4, &Index);
sq_getbool(v, 5, &Model);
((__SendDungeonInOut)0x86C8FC8)((void *)P, (void *)Player, Index, Model);
return 0;
}
static SQInteger register_World_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
{
sq_pushroottable(v);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
static void RegisterWorld(HSQUIRRELVM v)
{
// 获取游戏世界
register_World_func(v, Get_GameWorld, _SC("Sq_Get_GameWorld"));
// 根据UID获取Session
register_World_func(v, GameWorld_GetSessionByUid, _SC("Sq_GameWorld_GetSessionByUid"));
// 根据Session获取玩家
register_World_func(v, GameWorld_GetUserBySession, _SC("Sq_GameWorld_GetUserBySession"));
// 根据UID获取玩家
register_World_func(v, GameWorld_GetUserByUid, _SC("Sq_GameWorld_GetUserByUid"));
// 根据名字获取玩家
register_World_func(v, GameWorld_GetUserByName, _SC("Sq_GameWorld_GetUserByName"));
// 获取玩家数量
register_World_func(v, GameWorld_GetUserCount, _SC("Sq_GameWorld_GetUserCount"));
// 给所有玩家发包
register_World_func(v, GameWorld_SendAll, _SC("Sq_GameWorld_SendAll"));
// 指定玩家移动
register_World_func(v, GameWorld_MoveArea, _SC("Sq_GameWorld_MoveArea"));
// 给所有玩家发送队伍包
register_World_func(v, GameWorld_SendPartyInfoToAll, _SC("Sq_GameWorld_SendPartyInfoToAll"));
// 副本开启或关闭消息
register_World_func(v, GameWorld_SendDungeonInOut, _SC("Sq_GameWorld_SendDungeonInOut"));
// register_World_func(v, GetUserIdList, _SC("Sq_GetUserIdList"));
}

498
src/script/SqrReqScript.hpp Normal file
View File

@@ -0,0 +1,498 @@
#pragma once
#include "BASE64.hpp"
#include "Version.h"
#include <asio.hpp>
#include <asio/basic_socket_streambuf.hpp>
#include <asio/ssl.hpp>
#include <chrono>
#include <ctime>
#include <iostream>
#include <sstream>
#include <zlib.h>
using namespace asio;
using asio::ip::tcp;
// 单个字符解密
static char CutcodeChar(char c, int key, int key2) {
char a = (((c - 1) ^ key) ^ key2) - key;
return a;
}
// 解密
void Cutecode(char *pstr, int *pkey, int len, int keyLength) {
if (len == -1)
len = strlen(pstr);
for (int i = 0; i < len; i++) {
*(pstr + i) = CutcodeChar(*(pstr + i), pkey[i % keyLength],
pkey[(i + 18) % keyLength]);
}
}
// 加密函数
static std::string r_encryptDecrypt(const std::string &input,
const std::string &key) {
std::string output = input;
for (size_t i = 0; i < input.size(); i++) {
output[i] = input[i] ^ key[i % key.size()]; // 使用异或运算进行加密
}
return output;
}
static std::string ReqScriptUrl(const std::vector<std::string> &domains) {
for (const auto &domain : domains) {
try {
asio::io_context io_context;
asio::ssl::context ctx(asio::ssl::context::tlsv12_client);
ctx.set_verify_mode(asio::ssl::verify_none);
// 启用 TLS 1.0/1.1/1.2/1.3 支持
ctx.set_options(asio::ssl::context::default_workarounds |
asio::ssl::context::no_sslv2 |
asio::ssl::context::no_sslv3 |
asio::ssl::context::single_dh_use);
asio::ssl::stream<asio::ip::tcp::socket> socket(io_context, ctx);
// 设置 SNI
if (!SSL_set_tlsext_host_name(socket.native_handle(), domain.c_str())) {
asio::error_code ec{static_cast<int>(::ERR_get_error()),
asio::error::get_ssl_category()};
throw asio::system_error{ec};
}
asio::ip::tcp::resolver resolver(io_context);
auto endpoints = resolver.resolve(domain, "https");
// 连接超时设置
bool connect_timeout = false;
asio::steady_timer connect_timer(io_context);
connect_timer.expires_from_now(std::chrono::seconds(10));
connect_timer.async_wait([&](const asio::error_code &ec) {
if (!ec) {
connect_timeout = true;
socket.lowest_layer().close();
}
});
asio::error_code connect_ec;
asio::async_connect(socket.lowest_layer(), endpoints,
[&](asio::error_code ec, asio::ip::tcp::endpoint) {
connect_ec = ec;
connect_timer.cancel();
});
io_context.run();
io_context.reset();
if (connect_timeout) {
throw std::runtime_error("连接超时");
}
if (connect_ec) {
throw std::system_error(connect_ec);
}
// SSL握手超时设置
bool handshake_timeout = false;
asio::steady_timer handshake_timer(io_context);
handshake_timer.expires_from_now(std::chrono::seconds(10));
handshake_timer.async_wait([&](const asio::error_code &ec) {
if (!ec) {
handshake_timeout = true;
socket.lowest_layer().close();
}
});
asio::error_code handshake_ec;
socket.async_handshake(asio::ssl::stream_base::client,
[&](asio::error_code ec) {
handshake_ec = ec;
handshake_timer.cancel();
});
io_context.run();
io_context.reset();
if (handshake_timeout) {
throw std::runtime_error("SSL握手超时");
}
if (handshake_ec) {
throw std::system_error(handshake_ec);
}
std::string request = "POST /script/getservicenew HTTP/1.1\r\n";
request += "Host: " + domain + "\r\n";
request += "ve: " + std::string(DPS_SCRIPT_VERSION) + "\r\n";
request += "Content-Length: 0\r\n";
request += "Content-Type: application/x-www-form-urlencoded\r\n";
request += "Connection: close\r\n";
request += "\r\n";
asio::write(socket, asio::buffer(request));
// 响应超时设置
bool response_timeout = false;
asio::steady_timer response_timer(io_context);
response_timer.expires_from_now(std::chrono::seconds(10));
response_timer.async_wait([&](const asio::error_code &ec) {
if (!ec) {
response_timeout = true;
socket.lowest_layer().close();
}
});
asio::streambuf response;
asio::error_code read_ec;
asio::async_read(socket, response, [&](asio::error_code ec, std::size_t) {
read_ec = ec;
response_timer.cancel();
});
io_context.run();
if (response_timeout) {
throw std::runtime_error("响应超时");
}
if (read_ec && read_ec != asio::error::eof) {
throw std::system_error(read_ec);
}
// 解析响应头部
std::istream response_stream(&response);
std::string http_version;
unsigned int status_code;
std::string status_message;
response_stream >> http_version >> status_code;
std::getline(response_stream, status_message); // 读取状态行剩余部分
response_stream.ignore(); // 跳过状态行后的换行符
// 读取并解析头部字段
std::string header_line;
std::map<std::string, std::string> headers;
while (std::getline(response_stream, header_line) &&
header_line != "\r") {
// 去掉行末的\r
if (!header_line.empty() &&
header_line[header_line.size() - 1] == '\r') {
header_line.resize(header_line.size() - 1);
}
// 分割头部字段
size_t colon_pos = header_line.find(':');
if (colon_pos != std::string::npos) {
std::string key = header_line.substr(0, colon_pos);
std::string value = header_line.substr(colon_pos + 1);
// 去除值前面的空格
size_t start = value.find_first_not_of(" \t");
if (start != std::string::npos) {
value = value.substr(start);
}
headers[key] = value;
}
}
if (status_code == 200) {
// 读取响应体根据Content-Length
size_t content_length = 0;
auto cl_it = headers.find("Content-Length");
if (cl_it != headers.end()) {
content_length = std::stoul(cl_it->second);
}
// 计算剩余需要读取的字节数
size_t bytes_read = response.size();
size_t bytes_to_read =
content_length > bytes_read ? content_length - bytes_read : 0;
if (bytes_to_read > 0) {
// 继续读取剩余数据
response_timer.expires_from_now(std::chrono::seconds(10));
response_timer.async_wait([&](const asio::error_code &ec) {
if (!ec) {
response_timeout = true;
socket.lowest_layer().close();
}
});
asio::error_code read_body_ec;
asio::async_read(socket, response,
asio::transfer_exactly(bytes_to_read),
[&](asio::error_code ec, std::size_t) {
read_body_ec = ec;
response_timer.cancel();
});
io_context.run();
if (response_timeout) {
throw std::runtime_error("读取响应体超时");
}
if (read_body_ec && read_body_ec != asio::error::eof) {
throw std::system_error(read_body_ec);
}
}
// 提取响应体字符串
std::istreambuf_iterator<char> eos;
std::string response_body(
std::istreambuf_iterator<char>(response_stream), eos);
return response_body;
} else {
std::cerr << "错误的请求 " << domain
<< " failed with status code: " << status_code << std::endl;
}
} catch (const std::exception &e) {
std::cerr << "错误的连接 " << domain << ": " << e.what() << std::endl;
}
}
return "";
}
static std::string make_request(const std::string &host,
const std::string &port,
const std::string &path) {
asio::io_context io_context;
tcp::resolver resolver(io_context);
tcp::resolver::results_type endpoints = resolver.resolve(host, port);
tcp::socket socket(io_context);
asio::connect(socket, endpoints);
// Form the request. We specify the "Connection: close" header so that the
// server will close the socket after transmitting the response. This
// will allow us to treat all data up until the EOF as the content.
std::string request = "GET " + path + " HTTP/1.1\r\n";
request += "Host: " + host + "\r\n";
request += "Connection: close\r\n\r\n";
// Send the request.
asio::write(socket, asio::buffer(request));
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
asio::streambuf response;
asio::read_until(socket, response, "\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
throw std::runtime_error("Invalid response");
}
if (status_code != 200) {
throw std::runtime_error("Response returned with status code " +
std::to_string(status_code));
}
// Read the response headers, which are terminated by a blank line.
asio::read_until(socket, response, "\r\n\r\n");
// Process the response headers.
std::string header;
while (std::getline(response_stream, header) && header != "\r") {
// std::cout << header << "\n";
}
// std::cout << "\n";
// Write whatever content we already have to output.
std::ostringstream response_body;
if (response.size() > 0) {
response_body << &response;
}
// Read until EOF, writing data to output as we go.
asio::error_code error;
while (asio::read(socket, response, asio::transfer_at_least(1), error)) {
response_body << &response;
}
if (error != asio::error::eof) {
throw asio::system_error(error);
}
return response_body.str();
}
static std::string ReqScript(std::string url) {
std::vector<std::string> UrlData;
Tool::Split(url, UrlData, ",");
try {
std::string host = UrlData[0];
std::string port = UrlData[1];
std::string path = "/" + UrlData[2];
std::string response = make_request(host, port, path);
// std::cout << "Response body:\n"
// << response << "\n";
return response;
} catch (std::exception &e) {
// std::cerr << "Exception: " << e.what() << "\n";
return "null";
}
}
std::vector<unsigned char> base64_decode(const std::string &encoded) {
BIO *bio, *b64;
std::vector<unsigned char> result(encoded.size());
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bio = BIO_new_mem_buf(encoded.c_str(), encoded.size());
bio = BIO_push(b64, bio);
int len = BIO_read(bio, result.data(), encoded.size());
result.resize(len);
BIO_free_all(bio);
return result;
}
// zlib解压函数
static std::string gzip_decompress(std::vector<unsigned char> compressed) {
z_stream zs;
memset(&zs, 0, sizeof(zs));
if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK) {
// throw std::runtime_error("inflateInit failed");
return "null";
}
zs.next_in = (Bytef *)compressed.data();
zs.avail_in = compressed.size();
int ret;
char outbuffer[32768];
std::string outstring;
do {
zs.next_out = reinterpret_cast<Bytef *>(outbuffer);
zs.avail_out = sizeof(outbuffer);
ret = inflate(&zs, 0);
if (outstring.size() < zs.total_out) {
outstring.append(outbuffer, zs.total_out - outstring.size());
}
} while (ret == Z_OK);
inflateEnd(&zs);
if (ret != Z_STREAM_END) {
// throw std::runtime_error("Exception during zlib decompression: (" +
// std::to_string(ret) + ") " + zs.msg);
return "null";
}
return outstring;
}
static std::string rsaDecrypt(std::vector<unsigned char> encryptedData,
const std::string &publicKeyStr) {
RSA *rsa = RSA_new();
BIO *bio = BIO_new_mem_buf(const_cast<char *>(publicKeyStr.c_str()), -1);
PEM_read_bio_RSA_PUBKEY(bio, &rsa, NULL, NULL);
int rsaSize = RSA_size(rsa);
std::string decryptedData(rsaSize, 0);
int decryptedSize =
RSA_public_decrypt(encryptedData.size(), encryptedData.data(),
reinterpret_cast<unsigned char *>(&decryptedData[0]),
rsa, RSA_PKCS1_PADDING);
if (decryptedSize == -1) {
std::cerr << "Error decrypting data" << std::endl;
return "";
}
RSA_free(rsa);
BIO_free(bio);
decryptedData.resize(decryptedSize);
return decryptedData;
}
static void ReqSquirrelScript(HSQUIRRELVM v) {
std::vector<std::string> domains = {"dps.senzo.online"};
std::string StrBuf = ReqScriptUrl(domains);
std::vector<unsigned char> compressed = base64_decode(StrBuf);
std::string original_data = gzip_decompress(compressed);
nlohmann::json Jso = nlohmann::json::parse(original_data);
std::string Key = Jso["key"].dump();
Key = Key.substr(1, Key.length() - 2);
std::string Script = Jso["getBaseScriptStr"].dump();
Script = Script.substr(1, Script.length() - 2);
std::string pub = R"(-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDafyp7gGautPZZ3I3IlYLf8Qyw
xGigvg0rkmXPaP34C6sHi//GLuYjwM6AUJTtbfo0pCNmLqBbCiiuzkBXEqM+GeS2
+7zhu1yeEXv+i9iySFPbYydy851uVip7oqsbNM4iGYpS5ERND9XYuhSGUFI5p9ik
Nsvz+z7r4iT2rd8vrwIDAQAB
-----END PUBLIC KEY-----)";
std::string KeyString = rsaDecrypt(base64_decode(Key), pub);
std::vector<std::string> BaseDataBuffer;
Tool::Split(Script, BaseDataBuffer, "$$$$$");
size_t Ds = BaseDataBuffer.size();
int RealKey[20] = {0};
// 转换字符串到数组
for (size_t i = 0; i < KeyString.length() && i < 20; ++i) {
RealKey[i] = KeyString[i] - '0'; // 将字符转换为对应的数字
}
std::vector<std::string> BaseData;
for (size_t i = 0; i < (Ds - 1); i++) {
std::string str = BaseDataBuffer[i];
if (i % 2 != 0) {
// 得到有多少个逗号
std::vector<std::string> Data;
Tool::Split(str, Data, ", ");
size_t DDs = Data.size();
char *nutstr = new char[DDs + 1];
for (size_t s = 0; s < DDs; s++) {
nutstr[s] = char(atoi(Data[s].c_str()));
}
Cutecode(nutstr, RealKey, DDs, 20); // 解密
nutstr[DDs] = '\0';
std::string RealStr(nutstr, DDs + 1);
delete[] nutstr;
BaseData.push_back(RealStr);
} else {
BaseData.push_back(str);
}
}
for (size_t i = 0; i < BaseData.size(); i += 2) {
std::string Path = BaseData[i];
std::string Script = BaseData[i + 1];
// std::cout << Path << std::endl;
if (SQ_SUCCEEDED(sq_compilebuffer(v, (SQChar *)(Script.c_str()),
Script.length(), (SQChar *)(Path.c_str()),
true))) {
sq_pushroottable(v);
sq_call(v, 1, 1, 1);
sq_pop(v, 1);
}
}
}

501
src/script/l_squirrel.cpp Normal file
View File

@@ -0,0 +1,501 @@
#include "l_squirrel.h"
#include "l_squirrel_register.hpp"
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <iostream>
#include <ctime>
#include <sstream>
#include <chrono>
#include "SqrReqScript.hpp"
#include "Dio.hpp"
#include <sys/wait.h>
#include <openssl/aes.h>
#include <openssl/evp.h>
#define WEBSCRIPT true;
using asio::ip::tcp;
static char szGamePathA[256];
void setupLogger()
{
getConfigPath(szGamePathA, sizeof(szGamePathA));
std::string Path = std::string(szGamePathA);
std::string log_filename = "log/dps_log/" + Path.substr(Path.find("cfg") + 4) + "/log_";
char time_buffer[100];
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%d_%H-%M-%S", local_time);
log_filename += std::string(time_buffer) + ".txt";
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
console_sink->set_level(spdlog::level::info);
console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v");
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(log_filename, true);
file_sink->set_level(spdlog::level::info);
file_sink->set_pattern("[%Y-%m-%d %H:%M:%S] [%^%l%$] %v");
auto logger = std::make_shared<spdlog::logger>("logger", spdlog::sinks_init_list{ console_sink, file_sink });
logger->set_level(spdlog::level::info);
logger->flush_on(spdlog::level::info);
// logger->info("欢迎使用Dps插件");
spdlog::register_logger(logger);
spdlog::set_default_logger(logger);
}
// 虚拟机对象
HSQUIRRELVM v;
// Lock
std::recursive_mutex SqMtx;
static void printfunc(HSQUIRRELVM v, const SQChar* s, ...)
{
va_list vl;
va_start(vl, s);
char buf[1024];
vsnprintf(buf, sizeof(buf), s, vl);
va_end(vl);
spdlog::info(buf);
}
static void errorfunc(HSQUIRRELVM v, const SQChar* s, ...)
{
va_list vl;
va_start(vl, s);
char buf[1024];
vsnprintf(buf, sizeof(buf), s, vl);
va_end(vl);
spdlog::error(buf);
}
// 加密函数
static std::string encryptDecrypt(const std::string& input, const std::string& key)
{
std::string output = input;
for (size_t i = 0; i < input.size(); i++)
{
output[i] = input[i] ^ key[i % key.size()]; // 使用异或运算进行加密
}
return output;
}
// 判断是否处理加密
static std::string IsencryptDecrypt(const std::string& input, const std::string& FileName)
{
if (FileName.find(".nut") != std::string::npos)
return input;
else
return encryptDecrypt(input, "Rindro-Aurora");
}
static void ReloadingScript(HSQUIRRELVM v, std::string FilePath)
{
// 爬取出所有的脚本文件
std::vector<std::string> vec = Tool::GetListFilesR(FilePath);
std::vector<std::pair<std::string, std::string>> SquirrelFilePath;
// std::map<std::string, std::string>SquirrelFilePath;
for (auto it = vec.cbegin(); it != vec.cend(); ++it)
{
std::string FileName = FilePath + *it;
// std::cout << FileName << std::endl;
if (FileName.find(".nut") == std::string::npos && FileName.find(".sut") == std::string::npos)
continue;
std::fstream F;
F.open((FileName).c_str(), std::ios::in);
std::stringstream ContentStringStream;
ContentStringStream << F.rdbuf();
std::string ContentString(ContentStringStream.str());
F.close();
std::string RealContentString = IsencryptDecrypt(ContentString, FileName);
SquirrelFilePath.push_back({ FileName, RealContentString });
}
std::map<std::string, std::string> SquirrelLastFilePath;
for (auto it = SquirrelFilePath.begin(); it != SquirrelFilePath.end(); it++)
{
std::string Sourcename = it->first;
std::string ContentString = it->second;
if (SQ_SUCCEEDED(sq_compilebuffer(v, (SQChar*)(ContentString.c_str()), ContentString.length(), (SQChar*)(Sourcename.c_str()), true)))
{
sq_pushroottable(v);
sq_call(v, 1, 1, 1);
sq_pop(v, 1);
}
else
{
SquirrelLastFilePath[Sourcename] = ContentString;
}
}
while (SquirrelLastFilePath.size() > 0)
{
std::map<std::string, std::string> FailMapBuffer;
for (auto it = SquirrelLastFilePath.begin(); it != SquirrelLastFilePath.end(); it++)
{
std::string Sourcename = it->first;
std::string ContentString = it->second;
if (SQ_SUCCEEDED(sq_compilebuffer(v, (SQChar*)(ContentString.c_str()), ContentString.length(), (SQChar*)(Sourcename.c_str()), true)))
{
sq_pushroottable(v);
if (SQ_FAILED(sq_call(v, 1, 1, 1)))
{
FailMapBuffer[Sourcename] = ContentString;
};
sq_pop(v, 1);
};
}
SquirrelLastFilePath.clear();
if (FailMapBuffer.size() > 0)
{
for (auto it = FailMapBuffer.begin(); it != FailMapBuffer.end(); it++)
{
std::string Sourcename = it->first;
std::string ContentString = it->second;
SquirrelLastFilePath[Sourcename] = ContentString;
}
}
}
}
// 十六进制字符串转字节数组(完整实现)
std::vector<unsigned char> hex_to_bytes(const std::string& hex_str) {
std::vector<unsigned char> bytes;
// 检查Hex字符串长度是否为偶数
if (hex_str.size() % 2 != 0) {
throw std::invalid_argument("Hex string length must be even");
}
// 逐字节转换
for (size_t i = 0; i < hex_str.size(); i += 2) {
std::string byte_str = hex_str.substr(i, 2);
char* end_ptr;
unsigned long byte_val = strtol(byte_str.c_str(), &end_ptr, 16);
// 验证转换有效性
if (*end_ptr != '\0' || byte_val > 0xFF) {
throw std::invalid_argument("Invalid hex character: " + byte_str);
}
bytes.push_back(static_cast<unsigned char>(byte_val));
}
return bytes;
}
// 移除PKCS5Padding填充
std::string unpad_pkcs5(const std::string& data) {
if (data.empty()) return "";
unsigned char pad_len = data.back();
// 验证填充合法性:填充长度需≤块大小,且所有填充字节一致
if (pad_len > AES_BLOCK_SIZE || pad_len == 0) return data;
for (size_t i = data.size() - pad_len; i < data.size(); ++i) {
if (static_cast<unsigned char>(data[i]) != pad_len) {
return data; // 填充非法,返回原数据
}
}
return data.substr(0, data.size() - pad_len);
}
// AES-ECB解密输入二进制数据密钥固定字节数组
std::string aes_ecb_decrypt(const std::vector<unsigned char>& encrypted_data) {
// 用户提供的密钥16字节AES-128
const signed char keyBytes[] = { 92, -2, -65, 10, 118, 103, -68, 72, -23, 124, -103, -39, 0, -128, 31, -107 };
const int key_len = sizeof(keyBytes);
// 初始化AES解密密钥
AES_KEY aes_key;
if (AES_set_decrypt_key(reinterpret_cast<const unsigned char*>(keyBytes),
key_len * 8, // 16*8=128位
&aes_key) != 0) {
throw std::runtime_error("Invalid AES key");
}
// ECB模式分块解密AES块大小16字节
size_t data_len = encrypted_data.size();
std::vector<unsigned char> decrypt_buf(data_len);
for (size_t i = 0; i < data_len; i += AES_BLOCK_SIZE) {
// 最后一块不足16字节时补0ECB要求块对齐实际加密数据应为块大小整数倍
unsigned char block[AES_BLOCK_SIZE] = { 0 };
memcpy(block, encrypted_data.data() + i,
std::min(static_cast<size_t>(AES_BLOCK_SIZE), data_len - i));
AES_ecb_encrypt(block, decrypt_buf.data() + i, &aes_key, AES_DECRYPT);
}
// 移除PKCS5填充并返回字符串
return unpad_pkcs5(std::string(reinterpret_cast<char*>(decrypt_buf.data()), data_len));
}
static void LoadScript(HSQUIRRELVM v, bool Flag) {
std::ifstream f("/dp_s/_DPS_/FileConfig.json");
nlohmann::json Jso = nlohmann::json::parse(f);
f.close();
//加载基础脚本
for (const auto& elem : Jso["BaseScript"]) {
if (elem.is_string()) {
std::string line = elem.get<std::string>();
std::string file_path = "/dp_s/_DPS_/_Core/" + line;
// 以二进制模式打开加密文件
std::ifstream F(file_path, std::ios::binary | std::ios::in);
if (!F.is_open()) {
spdlog::error("无法打开脚本文件: {}", file_path);
continue;
}
// 直接读取二进制数据到vector<unsigned char>
std::vector<unsigned char> encrypted_data(
(std::istreambuf_iterator<char>(F)),
std::istreambuf_iterator<char>()
);
F.close();
std::string ContentString;
//外网解密版本
if (!Flag) {
try {
// 直接解密二进制数据
ContentString = aes_ecb_decrypt(encrypted_data);
if (ContentString.empty()) {
spdlog::warn("解密结果为空: {}", file_path);
continue;
}
}
catch (const std::runtime_error& e) {
spdlog::error("AES解密失败 {}: {}", file_path, e.what());
continue;
}
}
//本地不解密版本
else {
ContentString = std::string(reinterpret_cast<const char*>(encrypted_data.data()), encrypted_data.size());
}
if (SQ_SUCCEEDED(sq_compilebuffer(v, (SQChar*)(ContentString.c_str()), ContentString.length(), (SQChar*)(line.c_str()), true)))
{
sq_pushroottable(v);
sq_call(v, 1, SQTrue, SQFalse);
sq_pop(v, 1);
}
}
}
//加载项目脚本
for (const auto& elem : Jso["ProjectScript"]) {
for (const auto& path : elem["Script"]) {
if (path.is_string()) {
std::string line = path.get<std::string>();
std::string ContentString = "";
std::fstream F;
F.open(("/dp_s/_DPS_/_BuiltProject/" + line).c_str(), std::ios::in);
if (F.is_open()) {
std::stringstream ContentStringStream;
ContentStringStream << F.rdbuf();
ContentString = (ContentStringStream.str());
F.close();
}
if (SQ_SUCCEEDED(sq_compilebuffer(v, (SQChar*)(ContentString.c_str()), ContentString.length(), (SQChar*)(line.c_str()), true)))
{
sq_pushroottable(v);
sq_call(v, 1, SQTrue, SQFalse);
sq_pop(v, 1);
}
}
}
}
}
static SQInteger SqReloadScript(HSQUIRRELVM v)
{
if ((access("/dp_s/lib/db.ini", F_OK) != -1))
{
LoadScript(v, true);
}
else
{
LoadScript(v, false);
//读取网络单发脚本
ReqSquirrelScript(v);
}
return 0;
}
static std::string GetLocalScriptVersion() {
std::ifstream file("/dp_s/_DPS_/version"); // 打开文件
if (!file.is_open()) { // 检查文件是否成功打开
return "-1";
}
std::string content((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
content.pop_back();
return content;
}
static std::string GetRemoteScriptVersion() {
try {
asio::io_context io_context;
HttpsClient client(io_context);
// 配置GET请求
std::map<std::string, std::string> headers = {
{"User-Agent", "AsioHttpsClient/Sync"},
{"Accept", "application/json"},
{"Content-Type", "application/json"} // POST必须的头
};
client.setRequest("dps.senzo.online", "/script/getBaseUpdateTime", "POST", "", headers);
// 同步发送请求(阻塞等待结果)
HttpsClient::SyncResponse res = client.sendRequestSync();
// 处理结果
if (res.error.empty()) {
spdlog::info("获取到服务器最新脚本,版本为:{}", res.response);
return res.response;
}
else {
spdlog::info("请求服务器最新脚本失败,使用本地缓存脚本! 错误原因: {}", res.error);
return "error";
}
}
catch (const std::exception& e) {
spdlog::info("请求服务器最新脚本失败,使用本地缓存脚本! 错误原因: {}", e.what());
return "error";
}
}
int executeCommand(const std::string& cmd) {
pid_t pid = fork();
if (pid == -1) return -1;
if (pid == 0) { // 子进程
// 清除LD_PRELOAD
unsetenv("LD_PRELOAD");
// 执行命令(需拆分命令和参数)
execl("/bin/sh", "sh", "-c", cmd.c_str(), nullptr);
exit(1); // 若exec失败
}
// 父进程等待子进程结束
int status;
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
}
static void DownLoadScript(std::string RemoteVersion) {
try {
asio::io_context io_context;
HttpsClient client(io_context);
// 设置下载请求
client.setRequest("dps.senzo.online", "/script/getBaseSutZip", "GET");
// 下载文件
HttpsClient::FileDownloadResult result = client.downloadFileSync("/dp_s/_DPS_/cache.tar.gz");
if (!result.error.empty()) {
spdlog::info("下载服务器最新脚本失败,使用本地缓存脚本! 错误原因: {}", result.error);
}
else {
spdlog::info("服务器最新脚本下载完成! 正在解压...");
std::string command = "rm -rf \"" + std::string("/dp_s/_DPS_/_Core") + "\"";
int Res1 = executeCommand(command.c_str());
std::string tarPath = "/dp_s/_DPS_/cache.tar.gz";
std::string destDir = "/dp_s/_DPS_";
std::string tarCmd = " tar -xzf \"" + tarPath + "\" -C \"" + destDir + "\"";
int Res2 = executeCommand(tarCmd.c_str());
if (Res2 == 0) {
spdlog::info("解压成功!");
}
else {
spdlog::info("在解压过程中发生了一个预期之外的错误,请联系开发者!");
}
std::ofstream file("/dp_s/_DPS_/version", std::ios::out);
if (!file.is_open()) {
spdlog::info("发生了一个预期之外的错误,请联系开发者!");
}
file << RemoteVersion << std::endl;
file.close();
}
}
catch (const std::exception& e) {
spdlog::info("下载服务器最新脚本失败,使用本地缓存脚本! 错误原因: {}", e.what());
}
}
void InitSquirrel()
{
v = sq_open(8192); // 创建虚拟机其栈的初始大小为1024
sq_pushroottable(v);
sqstd_register_bloblib(v);
sqstd_register_iolib(v);
sqstd_register_systemlib(v);
sqstd_register_mathlib(v);
sqstd_register_stringlib(v);
// sqstd_register_dio(v);
sqstd_seterrorhandlers(v);
// 初始化日志器
setupLogger();
sq_setprintfunc(v, printfunc, errorfunc); // sets the print function
// 获取根表(全局作用域)
sq_pushroottable(v);
// 将DP_S_VERSION添加到全局表
sq_pushstring(v, "DP_S_VERSION", -1); // 键
sq_pushfloat(v, 25.332); // 值
sq_newslot(v, -3, SQFalse); // 在根表中创建slot
// 弹出根表,恢复堆栈
sq_pop(v, 1);
// 注册全局NutApi
GlobaRegisterSquirrel(v);
//非本地模式
if ((access("/dp_s/lib/db.ini", F_OK) == -1)) {
//获取本地脚本版本
std::string LocalVersion = GetLocalScriptVersion();
if (LocalVersion == "-1") {
spdlog::info("本地未检测到DP-S核心脚本,正在尝试联网获取最新脚本...");
}
else {
spdlog::info("本地DP-S核心脚本版本为{},正在检测是否有可用更新...", LocalVersion);
}
//获取服务器最新脚本版本
std::string RemoteVersion = GetRemoteScriptVersion();
if (RemoteVersion != "error") {
if (RemoteVersion != LocalVersion) {
spdlog::info("正在下载服务器最新脚本...");
//下载最新脚本
DownLoadScript(RemoteVersion);
}
else {
spdlog::info("当前服务器脚本已是最新版本无需更新.");
}
}
}
SqReloadScript(v);
// sq_pushroottable(v);
// sq_pushstring(v, "sq_ReloadScript", -1);
// sq_newclosure(v, SqReloadScript, 0); // create a new function
// sq_newslot(v, -3, SQFalse);
// sq_pop(v, 1); // pops the root table
}

31
src/script/l_squirrel.h Normal file
View File

@@ -0,0 +1,31 @@
#pragma once
#ifndef l_squirrel
#define l_squirrel
// #define SQUNICODE
#define NO_COMPILER
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include "Tool.h"
#include <map>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stdarg.h>
#include <mutex>
#ifdef SQUNICODE
#define scvprintf vfwprintf
#define scfprintf fwprintf
#else
#define scvprintf vfprintf
#define scfprintf fprintf
#endif
void InitSquirrel();
#endif

View File

@@ -0,0 +1,42 @@
#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include "SqrReg_User.hpp" //用户类
#include "SqrReg_Packet.hpp" //发包类
#include "SqrReg_World.hpp" //世界类
#include "SqrReg_Game.hpp" //游戏类
#include "SqrReg_GameManager.hpp" //游戏管理器类
#include "SqrReg_Party.hpp" //队伍类
#include "SqrReg_Inven.hpp" //背包类
#include "SqrReg_Battle_Field.hpp" //战斗对象类
#include "SqrReg_Dungeon.hpp" //副本类
#include "SqrReg_Memory.hpp" //内存类
#include "SqrReg_ActiveHook.hpp" //动态HOOK
#include "SqrReg_Dio.hpp" //网络类
#include "SqrReg_Asset.hpp" //资源类
#include "SqrReg_RSA.hpp" //RSA类
#include <iostream>
#include <stdarg.h>
static void GlobaRegisterSquirrel(HSQUIRRELVM v)
{
RegisterBattleField(v); // 战斗对象类
RegisterDungeon(v); // 副本类
RegisterInven(v); // 背包类
RegisterGameManager(v); // 游戏管理器类
RegisterParty(v); // 队伍类
RegisterGame(v); // 游戏类
RegisterWorld(v); // 世界类
RegisterPacket(v); // 发包类
RegisterUser(v); // 用户类
RegisterMemory(v); // 内存类
RegisterActiveHook(v); // 动态HOOK
RegisterDio(v); // 网络类
RegisterAsset(v); // 资源类
RegisterRsa(v); // RSA类
}