325 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			325 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | #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 <iostream>
 | |||
|  | 
 | |||
|  | 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(); | |||
|  | } | |||
|  | 
 | |||
|  | 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_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; | |||
|  | } | |||
|  | // 创建数据库连接池
 | |||
|  | 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; | |||
|  | } | |||
|  | 
 | |||
|  | 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 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, 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")); | |||
|  |     // 读取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")); | |||
|  |     // 创建数据库连接池
 | |||
|  |     register_World_func(v, L_CreatCConnectPool, _SC("Sq_CreatCConnectPool")); | |||
|  |     // 阻塞线程的数据库操作 无返回值
 | |||
|  |     register_World_func(v, L_MysqlExecNoRet, _SC("Sq_MysqlExecNoRet")); | |||
|  | } |