DP_S/include/SqrReg_Game.hpp

628 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 "l_socket.h"
#include <iostream>
#include <functional>
#include <list>
#include <ffi.h>
#define CONTAINS_STRING(str, substr) (str == substr)
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();
}
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();
}
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;
}
// 指针转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;
}
// 读内存字符串
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;
}
// 读取字节数组
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);
Address[Idx] = Buf;
// 这里-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;
}
// 通过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;
}
// 创建数据库连接池
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;
}
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;
}
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
}
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)
{
// 得到参数个数
SQInteger Count = sq_gettop(v);
// 得到函数地址
SQUserPointer FuncAddress;
sq_getuserpointer(v, 2, &FuncAddress);
// 得到返回值类型
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);
// 头部信息个数
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);
}
char *m = (char *)malloc(AdrSize);
void *bm = m;
// 定义函数签名
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++)
{
if (CONTAINS_STRING(ParameterType[0], "int"))
{
sq_getinteger(v, i, (SQInteger *)m);
args[CFlag] = &ffi_type_sint;
values[CFlag] = m;
m += sizeof(int);
}
else if (CONTAINS_STRING(ParameterType[0], "float"))
{
sq_getfloat(v, i, (SQFloat *)m);
args[CFlag] = &ffi_type_float;
values[CFlag] = m;
m += sizeof(float);
}
else if (CONTAINS_STRING(ParameterType[0], "bool"))
{
sq_getbool(v, i, (SQBool *)m);
args[CFlag] = &ffi_type_sint8;
values[CFlag] = m;
m += sizeof(bool);
}
else if (CONTAINS_STRING(ParameterType[0], "string"))
{
sq_getstring(v, i, (const SQChar **)m);
args[CFlag] = &ffi_type_pointer;
values[CFlag] = m;
m += sizeof(void *);
}
else if (CONTAINS_STRING(ParameterType[0], "pointer"))
{
sq_getuserpointer(v, i, (SQUserPointer *)m);
args[CFlag] = &ffi_type_pointer;
values[CFlag] = m;
m += sizeof(void *);
}
else if (CONTAINS_STRING(ParameterType[0], "short"))
{
sq_getinteger(v, i, (SQInteger *)m);
args[CFlag] = &ffi_type_sint16;
values[CFlag] = m;
m += sizeof(short);
}
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++;
}
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)
{
// 动态调用函数
ffi_call(&cif, FFI_FN(FuncAddress), &result, values);
}
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;
}
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;
}
static void RegisterGame(HSQUIRRELVM v)
{
getConfigPath(szGamePath, sizeof(szGamePath));
// int 和指针相互转换
register_World_func(v, L_Ptr2Int, _SC("Sq_Ptr2Int"));
register_World_func(v, L_Int2Ptr, _SC("Sq_Int2Ptr"));
register_World_func(v, L_S_Ptr, _SC("S_Ptr"));
// 获取频道配置
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"));
// 读地址字符串
register_World_func(v, L_ReadAddressString, _SC("Sq_ReadAddressString"));
// 读取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"));
// 通过ID从Pvf中查询Data
register_World_func(v, L_GetDataByIdFromPvf, _SC("Sq_GetDataByIdFromPvf"));
// 创建数据库连接池
register_World_func(v, L_CreatCConnectPool, _SC("Sq_CreatCConnectPool"));
// 阻塞线程的数据库操作 无返回值
register_World_func(v, L_MysqlExecNoRet, _SC("Sq_MysqlExecNoRet"));
// 创建Socket连接
register_World_func(v, L_CreatSocketConnect, _SC("Sq_CreatSocketConnect"));
register_World_func(v, L_CallFunc, _SC("Sq_CallFunc"));
}