2024-04-24 10:25:44 +08:00
|
|
|
|
#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"
|
2024-10-10 12:25:42 +08:00
|
|
|
|
#include "croncpp.h"
|
2024-04-30 03:01:48 +08:00
|
|
|
|
#include "l_socket.h"
|
2024-10-02 15:04:35 +08:00
|
|
|
|
#include <openssl/md5.h>
|
2024-10-24 10:20:13 +08:00
|
|
|
|
#include <opencc/opencc.h>
|
2024-04-24 10:25:44 +08:00
|
|
|
|
#include <iostream>
|
2024-04-30 03:01:48 +08:00
|
|
|
|
#include <functional>
|
|
|
|
|
|
#include <list>
|
2024-05-12 09:07:41 +08:00
|
|
|
|
#include <ffi.h>
|
2024-10-23 19:53:15 +08:00
|
|
|
|
#include <iconv.h>
|
2024-09-20 00:17:48 +08:00
|
|
|
|
#include "nlohmann/json.hpp"
|
2024-04-30 03:01:48 +08:00
|
|
|
|
|
2024-05-12 09:07:41 +08:00
|
|
|
|
#define CONTAINS_STRING(str, substr) (str == substr)
|
2024-04-24 10:25:44 +08:00
|
|
|
|
|
|
|
|
|
|
template <typename R, typename A, typename... ARG>
|
|
|
|
|
|
R CallGameT(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();
|
|
|
|
|
|
}
|
2024-05-12 09:07:41 +08:00
|
|
|
|
template <typename R>
|
|
|
|
|
|
R CallGameRT(void *call_addr, va_list arguments, std::vector<std::string> Type)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!call_addr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return R();
|
|
|
|
|
|
}
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// 使用汇编语言将va_list中的值一个一个push进去
|
|
|
|
|
|
R result;
|
|
|
|
|
|
va_list args;
|
|
|
|
|
|
va_copy(args, arguments);
|
|
|
|
|
|
|
|
|
|
|
|
asm volatile(
|
|
|
|
|
|
"pushl %0"
|
|
|
|
|
|
:
|
|
|
|
|
|
: "g"(va_arg(args, int))
|
|
|
|
|
|
: "memory");
|
|
|
|
|
|
|
|
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
|
|
|
|
asm volatile(
|
|
|
|
|
|
"call *%1"
|
|
|
|
|
|
: "=a"(result)
|
|
|
|
|
|
: "r"(call_addr)
|
|
|
|
|
|
: "memory");
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (...)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
return R();
|
|
|
|
|
|
}
|
2024-04-24 10:25:44 +08:00
|
|
|
|
|
|
|
|
|
|
static char szGamePath[256];
|
|
|
|
|
|
static int getargs(char ***argv)
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t buflen = 1024, readlen = 0, maxlen = buflen;
|
|
|
|
|
|
int fd = open("/proc/self/cmdline", O_RDONLY);
|
|
|
|
|
|
if (fd == -1)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
char *buf = (char *)malloc(buflen);
|
|
|
|
|
|
while (1)
|
|
|
|
|
|
{
|
|
|
|
|
|
ssize_t n = read(fd, buf + readlen, buflen - readlen);
|
|
|
|
|
|
if (n == -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
free(buf);
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
readlen += n;
|
|
|
|
|
|
if (!n || readlen < buflen)
|
|
|
|
|
|
break;
|
|
|
|
|
|
maxlen += buflen;
|
|
|
|
|
|
buf = (char *)realloc(buf, maxlen);
|
|
|
|
|
|
}
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
int argc = 0;
|
|
|
|
|
|
char *cp = buf;
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
while (*cp != '\0')
|
|
|
|
|
|
cp++;
|
|
|
|
|
|
argc++;
|
|
|
|
|
|
} while (++cp < buf + readlen);
|
|
|
|
|
|
*argv = (char **)malloc(argc * sizeof(char *));
|
|
|
|
|
|
argc = 0;
|
|
|
|
|
|
cp = buf;
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
(*argv)[argc] = (char *)malloc(strlen(cp) + 1);
|
|
|
|
|
|
strcpy((*argv)[argc], cp);
|
|
|
|
|
|
argc++;
|
|
|
|
|
|
while (*cp != '\0')
|
|
|
|
|
|
cp++;
|
|
|
|
|
|
} while (++cp < buf + readlen);
|
|
|
|
|
|
free(buf);
|
|
|
|
|
|
return argc;
|
|
|
|
|
|
}
|
|
|
|
|
|
static int getConfigPath(char *pPath, size_t nSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (readlink("/proc/self/exe", pPath, nSize) <= 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
char **argv = NULL;
|
|
|
|
|
|
int argc = getargs(&argv);
|
|
|
|
|
|
if (!argv || argc < 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (argv)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < argc; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (argv[i])
|
|
|
|
|
|
free(argv[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
free(argv);
|
|
|
|
|
|
}
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
*strrchr(pPath, '/') = '\0';
|
|
|
|
|
|
sprintf(pPath, "%s/cfg/%s.cfg", pPath, argv[1]);
|
|
|
|
|
|
for (int i = 0; i < argc; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (argv[i])
|
|
|
|
|
|
free(argv[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
free(argv);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
static SQInteger Game_GetConfig(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_pushstring(v, szGamePath, -1);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-18 11:35:30 +08:00
|
|
|
|
// 加密函数
|
|
|
|
|
|
static std::string Buf_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 Buf_IsencryptDecrypt(const std::string &input, const std::string &FileName)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (FileName.find(".nut") != std::string::npos)
|
|
|
|
|
|
return input;
|
|
|
|
|
|
else
|
|
|
|
|
|
return Buf_encryptDecrypt(input, "Lenheart-asdhfjiaednkljanslk");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 执行脚本
|
|
|
|
|
|
static SQInteger RunScript(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *Path;
|
|
|
|
|
|
sq_getstring(v, 2, &Path);
|
|
|
|
|
|
std::string RealPath(Path);
|
|
|
|
|
|
RealPath = "/dp_s/" + RealPath;
|
|
|
|
|
|
|
|
|
|
|
|
std::fstream F;
|
|
|
|
|
|
F.open(RealPath, std::ios::in);
|
|
|
|
|
|
std::stringstream ContentStringStream;
|
|
|
|
|
|
ContentStringStream << F.rdbuf();
|
|
|
|
|
|
std::string ContentString(ContentStringStream.str());
|
|
|
|
|
|
F.close();
|
|
|
|
|
|
|
|
|
|
|
|
std::string RealContentString = Buf_IsencryptDecrypt(ContentString, RealPath);
|
|
|
|
|
|
|
|
|
|
|
|
if (SQ_SUCCEEDED(sq_compilebuffer(v, (SQChar *)(RealContentString.c_str()), RealContentString.length(), (SQChar *)(RealPath.c_str()), true)))
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_pushroottable(v);
|
|
|
|
|
|
sq_call(v, 1, 1, 1);
|
|
|
|
|
|
sq_pop(v, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2024-04-24 10:25:44 +08:00
|
|
|
|
// 指针转int
|
|
|
|
|
|
static SQInteger L_Ptr2Int(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQUserPointer P;
|
|
|
|
|
|
sq_getuserpointer(v, 2, &P);
|
|
|
|
|
|
sq_pushinteger(v, (int)P);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
// int转指针
|
|
|
|
|
|
static SQInteger L_Int2Ptr(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQInteger Address;
|
|
|
|
|
|
sq_getinteger(v, 2, &Address);
|
|
|
|
|
|
sq_pushuserpointer(v, (void *)Address);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 写内存
|
|
|
|
|
|
static SQInteger L_WriteAddress(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 内存地址 int型
|
|
|
|
|
|
SQUserPointer Address;
|
|
|
|
|
|
// 内存偏移 int型
|
|
|
|
|
|
SQInteger Offset;
|
|
|
|
|
|
// 获取参数个数
|
|
|
|
|
|
int ParameterNum = sq_gettop(v);
|
|
|
|
|
|
// 2个参数时
|
|
|
|
|
|
if (ParameterNum == 4)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 获取地址
|
|
|
|
|
|
sq_getuserpointer(v, 2, &Address);
|
|
|
|
|
|
// 获取偏移
|
|
|
|
|
|
sq_getinteger(v, 3, &Offset);
|
|
|
|
|
|
// 获取修改的值
|
|
|
|
|
|
SQInteger WriteValue;
|
|
|
|
|
|
sq_getinteger(v, 4, &WriteValue);
|
|
|
|
|
|
|
|
|
|
|
|
*(int *)((void *)Address + Offset) = WriteValue;
|
|
|
|
|
|
sq_pushbool(v, true);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (ParameterNum == 5)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_pushbool(v, false);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 读内存
|
|
|
|
|
|
static SQInteger L_ReadAddress(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 内存地址 int型
|
|
|
|
|
|
SQUserPointer Address;
|
|
|
|
|
|
// 获取地址
|
|
|
|
|
|
sq_getuserpointer(v, 2, &Address);
|
|
|
|
|
|
sq_pushinteger(v, *(int *)Address);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
2024-09-17 11:41:25 +08:00
|
|
|
|
// 读内存
|
|
|
|
|
|
static SQInteger L_ReadPoint(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 内存地址 int型
|
|
|
|
|
|
SQUserPointer Address;
|
|
|
|
|
|
// 获取地址
|
|
|
|
|
|
sq_getuserpointer(v, 2, &Address);
|
|
|
|
|
|
int *ptr = reinterpret_cast<int *>(Address);
|
|
|
|
|
|
int value = *ptr;
|
|
|
|
|
|
sq_pushuserpointer(v, (void *)(value));
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
2024-04-30 03:01:48 +08:00
|
|
|
|
// 读内存字符串
|
|
|
|
|
|
static SQInteger L_ReadAddressString(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 内存地址 int型
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
2024-04-24 10:25:44 +08:00
|
|
|
|
|
|
|
|
|
|
// 读取字节数组
|
|
|
|
|
|
static SQInteger L_ReadByteArr(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQUserPointer P;
|
|
|
|
|
|
sq_getuserpointer(v, 2, &P);
|
|
|
|
|
|
SQInteger Count;
|
|
|
|
|
|
sq_getinteger(v, 3, &Count);
|
|
|
|
|
|
|
|
|
|
|
|
char *Address = (char *)P;
|
|
|
|
|
|
sq_newarray(v, 0);
|
|
|
|
|
|
for (size_t i = 0; i < Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_pushinteger(v, (int)(Address[i]));
|
|
|
|
|
|
sq_arrayappend(v, -2);
|
|
|
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 指针转Blob
|
|
|
|
|
|
static SQInteger L_Point2Blob(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQUserPointer P;
|
|
|
|
|
|
sq_getuserpointer(v, 2, &P);
|
|
|
|
|
|
SQInteger Count;
|
|
|
|
|
|
sq_getinteger(v, 3, &Count);
|
|
|
|
|
|
|
|
|
|
|
|
char *Address = (char *)P;
|
|
|
|
|
|
SQUserPointer Blobobj = sqstd_createblob(v, Count);
|
|
|
|
|
|
memcpy(Blobobj, P, Count);
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 写字节数组
|
|
|
|
|
|
static SQInteger L_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);
|
2024-09-15 13:08:42 +08:00
|
|
|
|
CMem::WriteUChar((Address + Idx), Buf);
|
2024-04-24 10:25:44 +08:00
|
|
|
|
// 这里-1是值,-2是键
|
|
|
|
|
|
sq_pop(v, 2); // 在下一次迭代之前弹出键和值
|
|
|
|
|
|
Idx++;
|
|
|
|
|
|
}
|
|
|
|
|
|
sq_pop(v, 1);
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 写Blob到指定地址
|
|
|
|
|
|
static SQInteger L_WriteBlobToAddress(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQUserPointer P;
|
|
|
|
|
|
sq_getuserpointer(v, 2, &P);
|
|
|
|
|
|
SQUserPointer Blobobj;
|
|
|
|
|
|
// sq_getuserpointer(v, 3, &P);
|
|
|
|
|
|
sqstd_getblob(v, 3, &Blobobj);
|
|
|
|
|
|
int Size = sqstd_getblobsize(v, 3);
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(P, Blobobj, Size);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 通过ID从Pvf中查询名称
|
|
|
|
|
|
static SQInteger L_GetNameByIdFromPvf(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQInteger Idx;
|
|
|
|
|
|
sq_getinteger(v, 2, &Idx);
|
|
|
|
|
|
|
|
|
|
|
|
void *Ret = CallGameT<void *>(0x835FA32, CallGameT<void *>(0x80CC19B), (unsigned int)Idx);
|
|
|
|
|
|
if (Ret)
|
|
|
|
|
|
{
|
|
|
|
|
|
const char *Name = CallGameT<const char *>(0x811ed82, Ret);
|
|
|
|
|
|
sq_pushstring(v, Name, -1);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_pushnull(v);
|
|
|
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
2024-04-30 03:01:48 +08:00
|
|
|
|
// 通过ID从Pvf中查询Data
|
|
|
|
|
|
static SQInteger L_GetDataByIdFromPvf(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQInteger Idx;
|
|
|
|
|
|
sq_getinteger(v, 2, &Idx);
|
|
|
|
|
|
|
|
|
|
|
|
void *Ret = CallGameT<void *>(0x835FA32, CallGameT<void *>(0x80CC19B), (unsigned int)Idx);
|
|
|
|
|
|
if (Ret)
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_pushuserpointer(v, Ret);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_pushnull(v);
|
|
|
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-24 10:25:44 +08:00
|
|
|
|
// 创建数据库连接池
|
|
|
|
|
|
static SQInteger L_CreatCConnectPool(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQInteger MinConnectCount, MaxConnectCount, Port;
|
|
|
|
|
|
const SQChar *Host;
|
|
|
|
|
|
const SQChar *Account;
|
|
|
|
|
|
const SQChar *Passwd;
|
|
|
|
|
|
|
|
|
|
|
|
sq_getinteger(v, 2, &MinConnectCount);
|
|
|
|
|
|
sq_getinteger(v, 3, &MaxConnectCount);
|
|
|
|
|
|
sq_getstring(v, 4, &Host);
|
|
|
|
|
|
sq_getinteger(v, 5, &Port);
|
|
|
|
|
|
sq_getstring(v, 6, &Account);
|
|
|
|
|
|
sq_getstring(v, 7, &Passwd);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化数据库
|
|
|
|
|
|
CConnectPool::CreatePool(MinConnectCount, MaxConnectCount, Host, Port, Account, Passwd);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 阻塞线程的数据库操作 无返回值
|
|
|
|
|
|
static SQInteger L_MysqlExecNoRet(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *Sql;
|
|
|
|
|
|
sq_getstring(v, 2, &Sql);
|
|
|
|
|
|
|
|
|
|
|
|
MYSQL *MysqlObject = CConnectPool::GetConnect();
|
|
|
|
|
|
mysql_query(MysqlObject, Sql);
|
|
|
|
|
|
CConnectPool::PutConnect(MysqlObject);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-30 03:01:48 +08:00
|
|
|
|
struct CreateSocketInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string Ip;
|
|
|
|
|
|
std::string Port;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void *SocketThread_function(void *arg)
|
|
|
|
|
|
{
|
|
|
|
|
|
CreateSocketInfo *Info = (CreateSocketInfo *)arg;
|
|
|
|
|
|
l_socket::getInstance().Init(Info->Ip, Info->Port);
|
|
|
|
|
|
delete Info;
|
|
|
|
|
|
// 在这里编写线程的具体操作
|
|
|
|
|
|
|
|
|
|
|
|
pthread_exit(NULL);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建Socket连接
|
|
|
|
|
|
static SQInteger L_CreatSocketConnect(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *Host;
|
|
|
|
|
|
const SQChar *Port;
|
|
|
|
|
|
sq_getstring(v, 2, &Host);
|
|
|
|
|
|
sq_getstring(v, 3, &Port);
|
|
|
|
|
|
CreateSocketInfo *Info = new CreateSocketInfo();
|
|
|
|
|
|
Info->Ip = Host;
|
|
|
|
|
|
Info->Port = Port;
|
|
|
|
|
|
|
|
|
|
|
|
pthread_t SocketThread;
|
|
|
|
|
|
// 创建线程1
|
|
|
|
|
|
if (pthread_create(&SocketThread, NULL, SocketThread_function, Info) != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::cerr << "Error creating thread 1" << std::endl;
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-24 10:25:44 +08:00
|
|
|
|
static SQInteger register_Game_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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-30 03:01:48 +08:00
|
|
|
|
static void Aprintfunc(const SQChar *s, ...)
|
|
|
|
|
|
{
|
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
va_list vl;
|
|
|
|
|
|
va_start(vl, s);
|
|
|
|
|
|
scvprintf(stdout, s, vl);
|
|
|
|
|
|
va_end(vl);
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CallFunc
|
|
|
|
|
|
static SQInteger L_CallFunc(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
2024-05-12 09:07:41 +08:00
|
|
|
|
// 得到参数个数
|
2024-04-30 03:01:48 +08:00
|
|
|
|
SQInteger Count = sq_gettop(v);
|
|
|
|
|
|
// 得到函数地址
|
|
|
|
|
|
SQUserPointer FuncAddress;
|
|
|
|
|
|
sq_getuserpointer(v, 2, &FuncAddress);
|
2024-05-12 09:07:41 +08:00
|
|
|
|
// 得到返回值类型
|
|
|
|
|
|
const SQChar *RetType;
|
|
|
|
|
|
sq_getstring(v, 3, &RetType);
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> ParameterType;
|
|
|
|
|
|
// 遍历参数类型数组
|
|
|
|
|
|
sq_pushnull(v); // null iterator
|
|
|
|
|
|
while (SQ_SUCCEEDED(sq_next(v, 4)))
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *path;
|
|
|
|
|
|
sq_getstring(v, -1, &path);
|
|
|
|
|
|
ParameterType.push_back(path);
|
|
|
|
|
|
sq_pop(v, 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
sq_pop(v, 1);
|
2024-04-30 03:01:48 +08:00
|
|
|
|
|
|
|
|
|
|
// 头部信息个数
|
2024-05-12 09:07:41 +08:00
|
|
|
|
int HeaderCount = 4;
|
|
|
|
|
|
|
|
|
|
|
|
// 计算valist内存
|
|
|
|
|
|
int AdrSize = 0;
|
|
|
|
|
|
for (std::string Type : ParameterType)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (CONTAINS_STRING(Type, "int"))
|
|
|
|
|
|
AdrSize += sizeof(int);
|
|
|
|
|
|
else if (CONTAINS_STRING(Type, "bool"))
|
|
|
|
|
|
AdrSize += sizeof(bool);
|
|
|
|
|
|
else if (CONTAINS_STRING(Type, "string"))
|
|
|
|
|
|
AdrSize += sizeof(char *);
|
|
|
|
|
|
else if (CONTAINS_STRING(Type, "float"))
|
|
|
|
|
|
AdrSize += sizeof(float);
|
|
|
|
|
|
else if (CONTAINS_STRING(Type, "pointer"))
|
|
|
|
|
|
AdrSize += sizeof(void *);
|
|
|
|
|
|
else if (CONTAINS_STRING(Type, "short"))
|
|
|
|
|
|
AdrSize += sizeof(short);
|
|
|
|
|
|
else if (CONTAINS_STRING(Type, "char"))
|
|
|
|
|
|
AdrSize += sizeof(char);
|
|
|
|
|
|
}
|
2024-04-30 03:01:48 +08:00
|
|
|
|
|
2024-05-12 09:07:41 +08:00
|
|
|
|
char *m = (char *)malloc(AdrSize);
|
2024-04-30 03:01:48 +08:00
|
|
|
|
void *bm = m;
|
2024-05-12 09:07:41 +08:00
|
|
|
|
// 定义函数签名
|
|
|
|
|
|
ffi_cif cif;
|
|
|
|
|
|
ffi_type **args = (ffi_type **)malloc(ParameterType.size() * sizeof(ffi_type *)); // 动态分配参数类型数组
|
|
|
|
|
|
void **values = (void **)malloc(ParameterType.size() * sizeof(void *)); // 动态分配参数值数组
|
|
|
|
|
|
ffi_arg result;
|
|
|
|
|
|
|
|
|
|
|
|
int CFlag = 0;
|
|
|
|
|
|
for (int i = (HeaderCount + 1); i < (Count + 1); i++)
|
2024-04-30 03:01:48 +08:00
|
|
|
|
{
|
2024-05-12 09:07:41 +08:00
|
|
|
|
if (CONTAINS_STRING(ParameterType[0], "int"))
|
2024-04-30 03:01:48 +08:00
|
|
|
|
{
|
2024-05-12 09:07:41 +08:00
|
|
|
|
sq_getinteger(v, i, (SQInteger *)m);
|
|
|
|
|
|
args[CFlag] = &ffi_type_sint;
|
|
|
|
|
|
values[CFlag] = m;
|
2024-04-30 03:01:48 +08:00
|
|
|
|
m += sizeof(int);
|
|
|
|
|
|
}
|
2024-05-12 09:07:41 +08:00
|
|
|
|
else if (CONTAINS_STRING(ParameterType[0], "float"))
|
2024-04-30 03:01:48 +08:00
|
|
|
|
{
|
2024-05-12 09:07:41 +08:00
|
|
|
|
sq_getfloat(v, i, (SQFloat *)m);
|
|
|
|
|
|
args[CFlag] = &ffi_type_float;
|
|
|
|
|
|
values[CFlag] = m;
|
2024-04-30 03:01:48 +08:00
|
|
|
|
m += sizeof(float);
|
|
|
|
|
|
}
|
2024-05-12 09:07:41 +08:00
|
|
|
|
else if (CONTAINS_STRING(ParameterType[0], "bool"))
|
2024-04-30 03:01:48 +08:00
|
|
|
|
{
|
2024-05-12 09:07:41 +08:00
|
|
|
|
sq_getbool(v, i, (SQBool *)m);
|
|
|
|
|
|
args[CFlag] = &ffi_type_sint8;
|
|
|
|
|
|
values[CFlag] = m;
|
2024-04-30 03:01:48 +08:00
|
|
|
|
m += sizeof(bool);
|
|
|
|
|
|
}
|
2024-05-12 09:07:41 +08:00
|
|
|
|
else if (CONTAINS_STRING(ParameterType[0], "string"))
|
2024-04-30 03:01:48 +08:00
|
|
|
|
{
|
2024-05-12 09:07:41 +08:00
|
|
|
|
|
|
|
|
|
|
sq_getstring(v, i, (const SQChar **)m);
|
|
|
|
|
|
args[CFlag] = &ffi_type_pointer;
|
|
|
|
|
|
values[CFlag] = m;
|
|
|
|
|
|
m += sizeof(void *);
|
2024-04-30 03:01:48 +08:00
|
|
|
|
}
|
2024-05-12 09:07:41 +08:00
|
|
|
|
else if (CONTAINS_STRING(ParameterType[0], "pointer"))
|
2024-04-30 03:01:48 +08:00
|
|
|
|
{
|
2024-05-12 09:07:41 +08:00
|
|
|
|
sq_getuserpointer(v, i, (SQUserPointer *)m);
|
|
|
|
|
|
args[CFlag] = &ffi_type_pointer;
|
|
|
|
|
|
values[CFlag] = m;
|
2024-04-30 03:01:48 +08:00
|
|
|
|
m += sizeof(void *);
|
|
|
|
|
|
}
|
2024-05-12 09:07:41 +08:00
|
|
|
|
else if (CONTAINS_STRING(ParameterType[0], "short"))
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_getinteger(v, i, (SQInteger *)m);
|
|
|
|
|
|
args[CFlag] = &ffi_type_sint16;
|
|
|
|
|
|
values[CFlag] = m;
|
|
|
|
|
|
m += sizeof(short);
|
2024-04-30 03:01:48 +08:00
|
|
|
|
}
|
2024-05-12 09:07:41 +08:00
|
|
|
|
else if (CONTAINS_STRING(ParameterType[0], "char"))
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_getinteger(v, i, (SQInteger *)m);
|
|
|
|
|
|
args[CFlag] = &ffi_type_schar;
|
|
|
|
|
|
values[CFlag] = m;
|
|
|
|
|
|
m += sizeof(char);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ParameterType.erase(ParameterType.begin());
|
|
|
|
|
|
CFlag++;
|
2024-04-30 03:01:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-12 09:07:41 +08:00
|
|
|
|
ffi_type *RetTypeFlag = &ffi_type_void;
|
|
|
|
|
|
|
|
|
|
|
|
std::string RetTypeString = RetType;
|
|
|
|
|
|
if (CONTAINS_STRING(RetTypeString, "int"))
|
|
|
|
|
|
RetTypeFlag = &ffi_type_sint;
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "float"))
|
|
|
|
|
|
RetTypeFlag = &ffi_type_float;
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "bool"))
|
|
|
|
|
|
RetTypeFlag = &ffi_type_sint8;
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "string"))
|
|
|
|
|
|
RetTypeFlag = &ffi_type_pointer;
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "pointer"))
|
|
|
|
|
|
RetTypeFlag = &ffi_type_pointer;
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "short"))
|
|
|
|
|
|
RetTypeFlag = &ffi_type_sint16;
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "char"))
|
|
|
|
|
|
RetTypeFlag = &ffi_type_schar;
|
|
|
|
|
|
|
|
|
|
|
|
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, CFlag, RetTypeFlag, args) == FFI_OK)
|
2024-04-30 03:01:48 +08:00
|
|
|
|
{
|
2024-05-12 09:07:41 +08:00
|
|
|
|
// 动态调用函数
|
|
|
|
|
|
ffi_call(&cif, FFI_FN(FuncAddress), &result, values);
|
2024-04-30 03:01:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-12 09:07:41 +08:00
|
|
|
|
free(args);
|
|
|
|
|
|
free(values);
|
|
|
|
|
|
free(bm);
|
|
|
|
|
|
|
|
|
|
|
|
if (CONTAINS_STRING(RetTypeString, "int"))
|
|
|
|
|
|
sq_pushinteger(v, (int)result);
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "float"))
|
|
|
|
|
|
sq_pushfloat(v, (float)result);
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "bool"))
|
|
|
|
|
|
sq_pushbool(v, (bool)result);
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "string"))
|
|
|
|
|
|
sq_pushstring(v, (char *)result, -1);
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "pointer"))
|
|
|
|
|
|
sq_pushuserpointer(v, (void *)result);
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "short"))
|
|
|
|
|
|
sq_pushinteger(v, (int)result);
|
|
|
|
|
|
else if (CONTAINS_STRING(RetTypeString, "char"))
|
|
|
|
|
|
sq_pushinteger(v, (int)result);
|
|
|
|
|
|
else
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
return 1;
|
2024-04-30 03:01:48 +08:00
|
|
|
|
}
|
2024-09-22 21:36:40 +08:00
|
|
|
|
|
2024-04-30 03:01:48 +08:00
|
|
|
|
static SQInteger L_S_Ptr(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *str;
|
|
|
|
|
|
sq_getstring(v, 2, &str);
|
|
|
|
|
|
unsigned long long addr = std::stoull(str, 0, 16);
|
|
|
|
|
|
void *ptr = reinterpret_cast<void *>(addr);
|
|
|
|
|
|
sq_pushuserpointer(v, ptr);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
2024-07-22 19:26:56 +08:00
|
|
|
|
static SQInteger L_Str_Ptr(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *str;
|
|
|
|
|
|
sq_getstring(v, 2, &str);
|
|
|
|
|
|
sq_pushuserpointer(v, (void *)str);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
2024-09-17 11:41:25 +08:00
|
|
|
|
static SQInteger L_Ptr_Operation_A2S(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 内存地址 int型
|
|
|
|
|
|
SQUserPointer Address;
|
|
|
|
|
|
// 获取地址
|
|
|
|
|
|
sq_getuserpointer(v, 2, &Address);
|
|
|
|
|
|
SQInteger Offset;
|
|
|
|
|
|
sq_getinteger(v, 3, &Offset);
|
|
|
|
|
|
sq_pushuserpointer(v, (void *)(Address + Offset));
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
2024-07-22 19:26:56 +08:00
|
|
|
|
|
|
|
|
|
|
static SQInteger New_Point(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQInteger Len;
|
|
|
|
|
|
sq_getinteger(v, 2, &Len);
|
|
|
|
|
|
void *P = malloc(Len);
|
|
|
|
|
|
sq_pushuserpointer(v, P);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
static SQInteger Delete_Point(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQUserPointer P;
|
|
|
|
|
|
sq_getuserpointer(v, 2, &P);
|
|
|
|
|
|
free(P);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2024-04-30 03:01:48 +08:00
|
|
|
|
|
2024-09-17 11:41:25 +08:00
|
|
|
|
static SQInteger Sq_getExportByName(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *MoudleName;
|
|
|
|
|
|
const SQChar *FuncName;
|
|
|
|
|
|
|
|
|
|
|
|
sq_getstring(v, 2, &MoudleName);
|
|
|
|
|
|
sq_getstring(v, 3, &FuncName);
|
|
|
|
|
|
|
|
|
|
|
|
void *handle = dlopen(nullptr, RTLD_LAZY);
|
|
|
|
|
|
if (!handle)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
void *targetFunctionPtr = dlsym(handle, FuncName);
|
|
|
|
|
|
if (!targetFunctionPtr)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
sq_pushuserpointer(v, targetFunctionPtr);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
2024-09-16 17:07:36 +08:00
|
|
|
|
|
2024-09-20 00:17:48 +08:00
|
|
|
|
static SQInteger OutPutTable(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *Str;
|
|
|
|
|
|
sq_getstring(v, 2, &Str);
|
|
|
|
|
|
|
|
|
|
|
|
nlohmann::json ex1 = nlohmann::json::parse(Str);
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << std::setw(4) << ex1 << std::endl;
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-02 15:04:35 +08:00
|
|
|
|
const std::string base64_chars =
|
|
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
|
|
|
|
"abcdefghijklmnopqrstuvwxyz"
|
|
|
|
|
|
"0123456789+/";
|
|
|
|
|
|
|
|
|
|
|
|
std::string base64_encode(const std::string &in)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string out;
|
|
|
|
|
|
int val = 0;
|
|
|
|
|
|
int valb = -6;
|
|
|
|
|
|
for (unsigned char c : in)
|
|
|
|
|
|
{
|
|
|
|
|
|
val = (val << 8) + c;
|
|
|
|
|
|
valb += 8;
|
|
|
|
|
|
while (valb >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
out.push_back(base64_chars[(val >> valb) & 0x3F]);
|
|
|
|
|
|
valb -= 6;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (valb > -6)
|
|
|
|
|
|
{
|
|
|
|
|
|
out.push_back(base64_chars[((val << 8) >> (valb + 8)) & 0x3F]);
|
|
|
|
|
|
}
|
|
|
|
|
|
while (out.size() % 4)
|
|
|
|
|
|
{
|
|
|
|
|
|
out.push_back('=');
|
|
|
|
|
|
}
|
|
|
|
|
|
return out;
|
|
|
|
|
|
}
|
|
|
|
|
|
std::string calculateMD5(const std::string &filePath)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::ifstream file(filePath, std::ios::binary | std::ios::ate);
|
|
|
|
|
|
if (!file)
|
|
|
|
|
|
{
|
|
|
|
|
|
return "";
|
|
|
|
|
|
}
|
|
|
|
|
|
std::streampos size = file.tellg();
|
|
|
|
|
|
file.seekg(0, std::ios::beg);
|
|
|
|
|
|
|
|
|
|
|
|
unsigned char buffer[16];
|
|
|
|
|
|
MD5_CTX md5Context;
|
|
|
|
|
|
MD5_Init(&md5Context);
|
|
|
|
|
|
|
|
|
|
|
|
while (file.read(reinterpret_cast<char *>(buffer), sizeof(buffer)))
|
|
|
|
|
|
{
|
|
|
|
|
|
MD5_Update(&md5Context, buffer, file.gcount());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MD5_Final(buffer, &md5Context);
|
|
|
|
|
|
|
|
|
|
|
|
file.close();
|
|
|
|
|
|
return base64_encode((char *)buffer);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void processDirectory(const std::string &directoryPath, std::unordered_map<std::string, std::string> &fileMD5Map)
|
|
|
|
|
|
{
|
|
|
|
|
|
DIR *dir;
|
|
|
|
|
|
struct dirent *entry;
|
|
|
|
|
|
|
|
|
|
|
|
if ((dir = opendir(directoryPath.c_str())) != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
while ((entry = readdir(dir)) != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (entry->d_type == DT_REG)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string filePath = directoryPath + "/" + entry->d_name;
|
|
|
|
|
|
std::string currentMD5 = calculateMD5(filePath);
|
|
|
|
|
|
|
|
|
|
|
|
if (fileMD5Map.find(filePath) != fileMD5Map.end())
|
|
|
|
|
|
{
|
|
|
|
|
|
if (fileMD5Map[filePath] != currentMD5)
|
|
|
|
|
|
{
|
|
|
|
|
|
fileMD5Map[filePath] = currentMD5;
|
|
|
|
|
|
std::lock_guard<std::recursive_mutex> lock(SqMtx);
|
|
|
|
|
|
// 执行虚拟机Main函数
|
|
|
|
|
|
SQInteger top = sq_gettop(v); // saves the stack size before the call
|
|
|
|
|
|
sq_pushroottable(v); // pushes the global table
|
|
|
|
|
|
sq_pushstring(v, _SC("_Reload_List_Write_"), -1);
|
|
|
|
|
|
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
|
|
|
|
|
{ // gets the field 'foo' from the global table
|
|
|
|
|
|
sq_pushroottable(v); // push the 'this' (in this case is the global table)
|
|
|
|
|
|
sq_pushstring(v, filePath.c_str(), -1);
|
|
|
|
|
|
sq_call(v, 2, SQFalse, SQTrue); // calls the function
|
|
|
|
|
|
}
|
|
|
|
|
|
sq_settop(v, top); // restores the original stack size
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
fileMD5Map[filePath] = currentMD5;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (entry->d_type == DT_DIR && std::string(entry->d_name) != "." && std::string(entry->d_name) != "..")
|
|
|
|
|
|
{
|
|
|
|
|
|
processDirectory(directoryPath + "/" + entry->d_name, fileMD5Map);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
closedir(dir);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
std::cerr << "无法打开目录:" << directoryPath << std::endl;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
struct AutoReloadSt
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string Path;
|
|
|
|
|
|
};
|
|
|
|
|
|
static void *continuousMonitoring(void *arg)
|
|
|
|
|
|
{
|
|
|
|
|
|
AutoReloadSt *Info = (AutoReloadSt *)arg;
|
|
|
|
|
|
std::unordered_map<std::string, std::string> fileMD5Map;
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
{
|
|
|
|
|
|
processDirectory(Info->Path, fileMD5Map);
|
|
|
|
|
|
usleep(1000); // 每隔 1 秒检查一次
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
static SQInteger AutoReload(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *Str;
|
|
|
|
|
|
sq_getstring(v, 2, &Str);
|
|
|
|
|
|
|
|
|
|
|
|
AutoReloadSt *Info = new AutoReloadSt();
|
|
|
|
|
|
Info->Path = std::string(Str);
|
|
|
|
|
|
// 开启DP-S 自动热重载
|
|
|
|
|
|
// std::string targetDirectory = (char *)Str;
|
|
|
|
|
|
// std::thread monitorThread(continuousMonitoring, targetDirectory);
|
|
|
|
|
|
// monitorThread.join();
|
|
|
|
|
|
|
|
|
|
|
|
pthread_t MonitoringThread;
|
|
|
|
|
|
// 创建线程1
|
|
|
|
|
|
if (pthread_create(&MonitoringThread, NULL, continuousMonitoring, Info) != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::cerr << "Error creating thread 1" << std::endl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-10 12:25:42 +08:00
|
|
|
|
static SQInteger L_Sq_Cron_Next(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *Str;
|
|
|
|
|
|
sq_getstring(v, 2, &Str);
|
|
|
|
|
|
SQInteger Date;
|
|
|
|
|
|
sq_getinteger(v, 3, &Date);
|
|
|
|
|
|
|
|
|
|
|
|
auto cron = cron::make_cron(Str);
|
|
|
|
|
|
std::time_t next = cron::cron_next(cron, Date);
|
|
|
|
|
|
sq_pushinteger(v, next);
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-23 19:53:15 +08:00
|
|
|
|
static SQInteger _stream_myreadstring(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQStream *self = NULL;
|
|
|
|
|
|
if (SQ_FAILED(sq_getinstanceup(v, 1, (SQUserPointer *)&self, (SQUserPointer)((SQUnsignedInteger)SQSTD_STREAM_TYPE_TAG), SQFalse)))
|
|
|
|
|
|
return sq_throwerror(v, _SC("invalid type tag"));
|
|
|
|
|
|
if (!self || !self->IsValid())
|
|
|
|
|
|
return sq_throwerror(v, _SC("the stream is invalid"));
|
|
|
|
|
|
|
|
|
|
|
|
SQInteger Count;
|
|
|
|
|
|
sq_getinteger(v, 2, &Count);
|
|
|
|
|
|
char *Str = new char[Count + 1];
|
|
|
|
|
|
self->Read(Str, Count);
|
|
|
|
|
|
std::string Sstr(Str, Count);
|
|
|
|
|
|
delete[] Str;
|
|
|
|
|
|
sq_pushstring(v, Sstr.c_str(), -1);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static SQInteger _CrcDecode(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
SQInteger Buffer[4];
|
|
|
|
|
|
|
|
|
|
|
|
sq_pushnull(v); // null iterator
|
|
|
|
|
|
int Idx = 0;
|
|
|
|
|
|
while (SQ_SUCCEEDED(sq_next(v, -2)))
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_getinteger(v, -1, &Buffer[Idx]);
|
|
|
|
|
|
Idx++;
|
|
|
|
|
|
sq_pop(v, 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
sq_pop(v, 1);
|
|
|
|
|
|
|
|
|
|
|
|
SQInteger crc32;
|
|
|
|
|
|
sq_getinteger(v, 3, &crc32);
|
|
|
|
|
|
|
|
|
|
|
|
int64 num = 2175242257;
|
|
|
|
|
|
int64 anInt = ((Buffer[0]) << 0) | ((Buffer[1]) << 8) | ((Buffer[2]) << 16) | ((Buffer[3]) << 24);
|
|
|
|
|
|
int64 val = (anInt ^ num ^ crc32);
|
|
|
|
|
|
int64 jiemi = (val >> 6) | ((val << (32 - 6)) & 0xFFFFFFFF);
|
|
|
|
|
|
|
|
|
|
|
|
sq_newarray(v, 0);
|
|
|
|
|
|
for (size_t i = 0; i < 4; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
sq_pushinteger(v, (jiemi >> (i * 8)) & 0xFF);
|
|
|
|
|
|
sq_arrayappend(v, -2);
|
|
|
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static SQInteger L_Conversion(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *Str;
|
|
|
|
|
|
sq_getstring(v, 2, &Str);
|
|
|
|
|
|
SQInteger Type;
|
|
|
|
|
|
sq_getinteger(v, 3, &Type);
|
|
|
|
|
|
|
|
|
|
|
|
std::string traditionalStr = std::string(Str);
|
2024-10-24 10:20:28 +08:00
|
|
|
|
// sq_pushnull(v);
|
|
|
|
|
|
opencc_t ot;
|
|
|
|
|
|
if (Type == 0)
|
|
|
|
|
|
ot = opencc_open(OPENCC_DEFAULT_CONFIG_TRAD_TO_SIMP);
|
|
|
|
|
|
else if (Type == 1)
|
|
|
|
|
|
ot = opencc_open(OPENCC_DEFAULT_CONFIG_SIMP_TO_TRAD);
|
|
|
|
|
|
|
|
|
|
|
|
char *NewStr = opencc_convert_utf8(ot, traditionalStr.c_str(), traditionalStr.length());
|
|
|
|
|
|
std::string RetStr(NewStr);
|
|
|
|
|
|
sq_pushstring(v, RetStr.c_str(), -1);
|
|
|
|
|
|
opencc_convert_utf8_free(NewStr);
|
|
|
|
|
|
opencc_close(ot);
|
2024-10-23 19:53:15 +08:00
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static SQInteger L_GetTimestampString(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
auto now = std::chrono::system_clock::now();
|
|
|
|
|
|
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
|
|
|
|
|
|
auto value = now_ms.time_since_epoch();
|
|
|
|
|
|
long long milliseconds = value.count();
|
|
|
|
|
|
|
|
|
|
|
|
std::ostringstream oss;
|
|
|
|
|
|
oss << milliseconds;
|
|
|
|
|
|
|
|
|
|
|
|
sq_pushstring(v, oss.str().c_str(), -1);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-10 20:14:37 +08:00
|
|
|
|
#define NSUBHOOK_INIT(func, addr) \
|
|
|
|
|
|
fn##func func = (fn##func)addr; \
|
|
|
|
|
|
FuncHook h##func
|
|
|
|
|
|
#define NSUBHOOK_SETUP(func) h##func.Hook((void **)&func, (void *)_##func)
|
|
|
|
|
|
|
|
|
|
|
|
typedef int (*fnInven_Item_reset)(void *a1);
|
|
|
|
|
|
|
|
|
|
|
|
typedef void *(*fnInven_Item_setcopy)(void *a1, void *a2);
|
|
|
|
|
|
NSUBHOOK_INIT(Inven_Item_reset, 0x080CB7D8);
|
|
|
|
|
|
int _Inven_Item_reset(void *item)
|
|
|
|
|
|
{
|
|
|
|
|
|
int ret = Inven_Item_reset(item);
|
|
|
|
|
|
memset(item, 0, 61);
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
NSUBHOOK_INIT(Inven_Item_setcopy, 0x0814A62E);
|
|
|
|
|
|
void *_Inven_Item_setcopy(void *item, void *item2)
|
|
|
|
|
|
{
|
|
|
|
|
|
Inven_Item_setcopy(item, item2);
|
|
|
|
|
|
memcpy(item, item2, 61);
|
|
|
|
|
|
return item2;
|
|
|
|
|
|
}
|
|
|
|
|
|
static SQInteger L_HookEquimentUseJewel(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
NSUBHOOK_SETUP(Inven_Item_setcopy);
|
|
|
|
|
|
NSUBHOOK_SETUP(Inven_Item_reset);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-27 20:24:19 +08:00
|
|
|
|
static SQInteger LongLongOperation(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
const SQChar *valuebuf1;
|
|
|
|
|
|
sq_getstring(v, 2, &valuebuf1);
|
|
|
|
|
|
long long value1 = std::atoll(valuebuf1);
|
|
|
|
|
|
|
|
|
|
|
|
const SQChar *valuebuf2;
|
|
|
|
|
|
sq_getstring(v, 3, &valuebuf2);
|
|
|
|
|
|
long long value2 = std::atoll(valuebuf2);
|
|
|
|
|
|
|
|
|
|
|
|
const SQChar *TypeBuf;
|
|
|
|
|
|
sq_getstring(v, 4, &TypeBuf);
|
|
|
|
|
|
std::string Type(TypeBuf);
|
|
|
|
|
|
|
|
|
|
|
|
std::string RetString = "";
|
|
|
|
|
|
if (Type == "+")
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string(value1 + value2);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (Type == "-")
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string(value1 - value2);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (Type == "*")
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string((static_cast<double>(value1) * static_cast<double>(value2)));
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (Type == "/")
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string((static_cast<double>(value1) / static_cast<double>(value2)));
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (Type == "%")
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string(value1 % value2);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (Type == "format")
|
|
|
|
|
|
{
|
|
|
|
|
|
if (value1 < 1000)
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string(value1);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (value1 < 1000000)
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string(value1 / 1000.0) + "k";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (value1 < 1000000000)
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string(value1 / 1000000.0) + "M";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (value1 < 1000000000000LL)
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string(value1 / 1000000000.0) + "G";
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
RetString = std::to_string(value1 / 1000000000000.0) + "T";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
sq_pushstring(v, RetString.c_str(), -1);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-24 10:25:44 +08:00
|
|
|
|
static void RegisterGame(HSQUIRRELVM v)
|
|
|
|
|
|
{
|
|
|
|
|
|
getConfigPath(szGamePath, sizeof(szGamePath));
|
|
|
|
|
|
|
2024-10-23 19:53:15 +08:00
|
|
|
|
// 获取字符串时间戳
|
|
|
|
|
|
register_World_func(v, L_GetTimestampString, _SC("Sq_GetTimestampString"));
|
|
|
|
|
|
|
|
|
|
|
|
// 简繁转换
|
|
|
|
|
|
register_World_func(v, L_Conversion, _SC("Sq_Conversion"));
|
|
|
|
|
|
|
2024-10-10 12:25:42 +08:00
|
|
|
|
// 获取下一个cron
|
|
|
|
|
|
register_World_func(v, L_Sq_Cron_Next, _SC("Sq_Cron_Next"));
|
2024-10-23 19:53:15 +08:00
|
|
|
|
// 自身封装读取流
|
|
|
|
|
|
register_World_func(v, _stream_myreadstring, _SC("stream_myreadstring"));
|
|
|
|
|
|
register_World_func(v, _CrcDecode, _SC("Sq_CrcDecode"));
|
2024-10-10 12:25:42 +08:00
|
|
|
|
|
2024-04-24 10:25:44 +08:00
|
|
|
|
// int 和指针相互转换
|
2024-09-18 11:35:30 +08:00
|
|
|
|
register_World_func(v, RunScript, _SC("sq_RunScript"));
|
|
|
|
|
|
|
2024-04-24 10:25:44 +08:00
|
|
|
|
register_World_func(v, L_Ptr2Int, _SC("Sq_Ptr2Int"));
|
|
|
|
|
|
register_World_func(v, L_Int2Ptr, _SC("Sq_Int2Ptr"));
|
2024-04-30 03:01:48 +08:00
|
|
|
|
register_World_func(v, L_S_Ptr, _SC("S_Ptr"));
|
2024-07-22 19:26:56 +08:00
|
|
|
|
register_World_func(v, L_Str_Ptr, _SC("Str_Ptr"));
|
|
|
|
|
|
|
2024-09-20 00:17:48 +08:00
|
|
|
|
// 指针运算
|
2024-09-17 11:41:25 +08:00
|
|
|
|
register_World_func(v, L_Ptr_Operation_A2S, _SC("Ptr_Operation_A2S"));
|
|
|
|
|
|
|
2024-07-22 19:26:56 +08:00
|
|
|
|
// new一个指针
|
|
|
|
|
|
register_World_func(v, New_Point, _SC("Sq_New_Point"));
|
|
|
|
|
|
// 销毁一个指针
|
|
|
|
|
|
register_World_func(v, Delete_Point, _SC("Sq_Delete_Point"));
|
2024-04-24 10:25:44 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取频道配置
|
|
|
|
|
|
register_World_func(v, Game_GetConfig, _SC("Sq_Game_GetConfig"));
|
|
|
|
|
|
// 写地址int
|
|
|
|
|
|
register_World_func(v, L_WriteAddress, _SC("Sq_WriteAddress"));
|
|
|
|
|
|
// 读地址int
|
|
|
|
|
|
register_World_func(v, L_ReadAddress, _SC("Sq_ReadAddress"));
|
2024-09-17 11:41:25 +08:00
|
|
|
|
// 读地址Point
|
|
|
|
|
|
register_World_func(v, L_ReadPoint, _SC("Sq_ReadPoint"));
|
2024-04-30 03:01:48 +08:00
|
|
|
|
// 读地址字符串
|
|
|
|
|
|
register_World_func(v, L_ReadAddressString, _SC("Sq_ReadAddressString"));
|
2024-04-24 10:25:44 +08:00
|
|
|
|
// 读取Byte
|
|
|
|
|
|
register_World_func(v, L_ReadByteArr, _SC("Sq_ReadByteArr"));
|
|
|
|
|
|
// 写入Byte
|
|
|
|
|
|
register_World_func(v, L_WriteByteArr, _SC("Sq_WriteByteArr"));
|
|
|
|
|
|
// 通过指针转Blob
|
|
|
|
|
|
register_World_func(v, L_Point2Blob, _SC("Sq_Point2Blob"));
|
|
|
|
|
|
// 写Blob到指定地址
|
|
|
|
|
|
register_World_func(v, L_WriteBlobToAddress, _SC("Sq_WriteBlobToAddress"));
|
|
|
|
|
|
// 通过ID从Pvf中查询名称
|
|
|
|
|
|
register_World_func(v, L_GetNameByIdFromPvf, _SC("Sq_GetNameByIdFromPvf"));
|
2024-04-30 03:01:48 +08:00
|
|
|
|
// 通过ID从Pvf中查询Data
|
|
|
|
|
|
register_World_func(v, L_GetDataByIdFromPvf, _SC("Sq_GetDataByIdFromPvf"));
|
2024-04-24 10:25:44 +08:00
|
|
|
|
// 创建数据库连接池
|
|
|
|
|
|
register_World_func(v, L_CreatCConnectPool, _SC("Sq_CreatCConnectPool"));
|
|
|
|
|
|
// 阻塞线程的数据库操作 无返回值
|
|
|
|
|
|
register_World_func(v, L_MysqlExecNoRet, _SC("Sq_MysqlExecNoRet"));
|
2024-04-30 03:01:48 +08:00
|
|
|
|
// 创建Socket连接
|
|
|
|
|
|
register_World_func(v, L_CreatSocketConnect, _SC("Sq_CreatSocketConnect"));
|
2024-09-20 00:17:48 +08:00
|
|
|
|
// 动态调用Call
|
2024-04-30 03:01:48 +08:00
|
|
|
|
register_World_func(v, L_CallFunc, _SC("Sq_CallFunc"));
|
2024-09-20 00:17:48 +08:00
|
|
|
|
// 获取模块函数地址
|
2024-09-17 11:41:25 +08:00
|
|
|
|
register_World_func(v, Sq_getExportByName, _SC("Sq_getExportByName"));
|
2024-09-20 00:17:48 +08:00
|
|
|
|
// 打印表
|
|
|
|
|
|
register_World_func(v, OutPutTable, _SC("Sq_OutPutTable"));
|
2024-10-02 15:04:35 +08:00
|
|
|
|
// 开启自动热重载
|
|
|
|
|
|
register_World_func(v, AutoReload, _SC("Sq_AutoReload"));
|
2024-12-10 20:14:37 +08:00
|
|
|
|
// Hook装备镶嵌
|
|
|
|
|
|
register_World_func(v, L_HookEquimentUseJewel, _SC("L_HookEquimentUseJewel"));
|
2025-03-27 20:24:19 +08:00
|
|
|
|
//大数字计算
|
|
|
|
|
|
register_World_func(v, LongLongOperation, _SC("Sq_LongLongOperation"));
|
2024-09-16 17:07:36 +08:00
|
|
|
|
}
|