This commit is contained in:
aixianling
2025-01-09 17:45:40 +08:00
commit 5c9f1dae4a
3482 changed files with 1146531 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

486
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,486 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动跨服DBServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/CS/DBServer/dbserver_d",
"args": ["${workspaceFolder}/CS/DBServer/DBServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动DBServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/Exec/DBServer/dbserver_d",
"args": ["${workspaceFolder}/Exec/DBServer/DBServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动跨服gateway",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/CS/Gateway/gateway_d",
"args": ["${workspaceFolder}/CS/Gateway/GateWay.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "/home/cwl/common/libs;/home/cwl/srvlib/libs;/home/cwl/common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动gateway",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/Exec/Gateway/gateway_d",
"args": ["${workspaceFolder}/Exec/Gateway/GateWay.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动跨服LogicServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/CS/LogicServer/logicserver_d",
"args": ["${workspaceFolder}/CS/LogicServer/LogicServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "/home/cwl/common/libs;/home/cwl/srvlib/libs;/home/cwl/common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动LogicServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/Exec/LogicServer/logicserver_d",
"args": ["${workspaceFolder}/Exec/LogicServer/LogicServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "/home/cwl/common/libs;/home/cwl/srvlib/libs;/home/cwl/common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动Robot",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/Exec/LogicServer/robot_d",
"args": ["${workspaceFolder}/Exec/LogicServer/LogicServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启动Robot",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "/home/cwl/common/libs;/home/cwl/srvlib/libs;/home/cwl/common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动RobotGate",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/Exec/RobotGate/robootgate_d",
"args": ["${workspaceFolder}/Exec/RobotGate/GateServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启动Robot",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "/home/cwl/common/libs;/home/cwl/srvlib/libs;/home/cwl/common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动LocalLogServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../Exec/LocalLogServer/locallogserver_d",
"args": ["${workspaceFolder}/../Exec/LocalLogServer/LocallogServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动LoggerServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../Exec/LoggerServer/loggerserver_d",
"args": ["${workspaceFolder}/../Exec/LoggerServer/LoggerServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动NameServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../Exec/NameServer/nameserver_d",
"args": ["${workspaceFolder}/../Exec/NameServer/NameServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动AmServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../Exec/AMServer/amserver_d",
"args": ["${workspaceFolder}/../Exec/AMServer/AMServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动SessionServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../Exec/SessionServer/sessionserver_d",
"args": ["${workspaceFolder}/../Exec/SessionServer/SessionServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 启动BackStageServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../Exec/BackStageServer/backstageserver_d",
"args": ["${workspaceFolder}/../Exec/BackStageServer/BackStageServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
]
}

BIN
Gateway/.DS_Store vendored Normal file

Binary file not shown.

60
Gateway/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,60 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动GateServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/Gateway/gateway_d",
"args": ["${workspaceFolder}/build/Gateway/GateWay.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 附加GateServer",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../build/GateServer/gateserver_d",
"processId": "${command:pickProcess}",
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/common/libs;${workspaceFolder}/srvlib/libs;${workspaceFolder}/../../common/cpp/libs/3rd/bin;"
}
]
}

74
Gateway/CMakeLists.txt Normal file
View File

@@ -0,0 +1,74 @@
cmake_minimum_required (VERSION 2.8.1)
PROJECT(Server)
set( CMAKE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../sdk) # include 文件夹
#头文件
include_directories(
${CMAKE_INCLUDE_DIR}/lua-5.1/src
${CMAKE_INCLUDE_DIR}/tolua++/src
srvlib/include/
srvlib/3rd/lua/
srvlib/3rd/zlib/
srvlib/3rd/tolua++/
srvlib/3rd/mysql/
common/
)
# Win10 / Linux 环境下的处理
if(MSVC)
# 头文件
include_directories(srvlib/3rd/mysql)
# 工具路径
SET(PATH_LUA "${CMAKE_SOURCE_DIR}/srvlib/bin/lua514")
SET(PATH_TOLUA "${CMAKE_SOURCE_DIR}/srvlib/bin/tolua++")
# 编译选项
ADD_DEFINITIONS(/W3 /wd"4996" /wd"4819" /wd"4091" /wd"4099" /wd"4800" /wd"4996")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /MP4")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
else()
# 头文件
include_directories(/usr/local/mysql/include)
# 编译选项
set(CMAKE_C_FLAGS "-O0 -g3 -gdwarf-2 -std=c++0x -c -fmessage-length=0 -MMD -MP")
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -Wall -Wextra -Wfatal-errors -std=c++11 -fpermissive -D_DEBUG -g -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "-O0 -g3 -Wall -std=c++11 -fpermissive -g -ggdb -DNDEBUG")
#add_definitions("-O0 -g3 -gdwarf-2 -std=c++11 -w -c -fmessage-length=0 -MMD -MP")
endif(MSVC)
# 项目内文件分组工具
function(group_by_dir source_dir)
message(STATUS "${ARGV0}")
foreach(FILE ${ARGN})
message(STATUS "${FILE}")
# 获取文件绝对路径
get_filename_component(FULL_NAME "${FILE}" ABSOLUTE)
# 获取文件父路径
get_filename_component(PARENT_DIR "${FULL_NAME}" PATH)
# 移除父路径中的源码根路径
string(REPLACE "${ARGV0}" "" GROUP "${PARENT_DIR}")
# 确保路径使用windows路径符号
string(REPLACE "/" "\\" GROUP "${GROUP}")
# 分组
source_group("${GROUP}" FILES "${FILE}")
endforeach()
endfunction(group_by_dir)
set( Root_Dir ${PROJECT_SOURCE_DIR} )
set( Libs_Dir
${PROJECT_SOURCE_DIR}/libs/gateway
${PROJECT_SOURCE_DIR}/../common/cpp/libs/3rd/bin
)
set( Bin_Dir ${PROJECT_SOURCE_DIR} )
SET(EXECUTABLE_OUTPUT_PATH ${Bin_Dir})
# 子路径
add_subdirectory(srvlib)
add_subdirectory(common)
add_subdirectory(gateway)

5
Gateway/build.bat Normal file
View File

@@ -0,0 +1,5 @@
@echo off
mkdir VS_Proj
cd VS_Proj
cmake .. -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=Debug
pause

20
Gateway/build.sh Normal file
View File

@@ -0,0 +1,20 @@
#!/bin/bash
cd $(cd "$(dirname "$0")" && pwd)
srcDIR=`pwd`
temp="/../temp"
name="/BuildGateway"
#cd gameworld/script/tolua++
#tolua++ -n server -o serverInterface.cc serverInterface.scp
#mkdir $srcDIR$temp
#mkdir $srcDIR$temp$name
mkdir temp_BuildGateway
cd temp_BuildGateway
if [ -n "$1" ]; then
BuiltType=$1
else
BuiltType=Release
fi
cmake .. -DCMAKE_BUILD_TYPE=${BuiltType}
make -j2
#svn log -l 1 > web/server.version

BIN
Gateway/common/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,26 @@
cmake_minimum_required (VERSION 2.8.1)
set( CMAKE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../sdk) # include 文件夹
#头文件
include_directories(
${CMAKE_INCLUDE_DIR}/public
${CMAKE_INCLUDE_DIR}/system
${CMAKE_INCLUDE_DIR}/utils
${CMAKE_INCLUDE_DIR}/lua-5.1/src
${CMAKE_INCLUDE_DIR}/tolua++/src
./
)
# 源文件及头文件
file(GLOB_RECURSE Common_LIST "${PROJECT_SOURCE_DIR}/common/*.cc" "${PROJECT_SOURCE_DIR}/common/*.h")
# 项目文件分组
group_by_dir( ${PROJECT_SOURCE_DIR}/common ${Common_LIST} )
# 输出目录
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${Root_Dir}/../libs/gateway)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${Root_Dir}/../libs/gateway)
#生成目标
add_library(common STATIC ${Common_LIST})

View File

@@ -0,0 +1,504 @@
#pragma once
/****************************************************************************************
* 服务端之间通信协议定义
* 命名规范:
* namespace 服务端名称Proto
* {
* enum e目标服务端名称Code
* {
* //通信消息号注释数据段格式数据名称数据类型【byte,short,int,shortString,string】
* c消息号别名 = 消息号值其中c表示通信双方中的客户端方发送从1开始
* //通信消息号注释数据段格式数据名称数据类型【byte,short,int,shortString,string】
* s消息号别名 = 消息号值其中s表示通信双方中的服务端方发送从1开始
* };
* };
****************************************************************************************/
namespace InterSrvComm
{
static const int DBSER_VER = 161122;
namespace DbServerProto
{
enum SystemId
{
siDefault = 0, //特殊命令
siActor = 1,
siGuild = 2,
siConsignment = 3,
siMsg = 4,
siRank = 5,
siGlobal = 6,
siFight = 7,
siMail = 8,
siCommon = 9,
siConfig = 10,
siWarTeam = 11,
siTxApi = 12,
siCommonDB = 13,
siAuction = 14,
siTrading = 15,
};
enum DefaultSysId
{
dcInitDB = 1, //初始化数据库,特殊指令
dcExecDB = 2, //执行sql语句
};
/**数据服务器和逻辑服务器的命令码**/
// 部分在脚本使用到了,所以不要任意修改
// 注意:部分的数据在跨服战中不用读取,部分是读取但不用保存
enum EntityMgrId
{
dcDefault, //默认处理0
// g-d
dcQuery = 1, //查询数据
dcSave = 2, //保存数据 actors
dcSaveRole, // roles
dcSaveVar, //加载角色变量 actorvariable.variable
dcSaveItem, // items
dcSaveMail,
dcSaveStore,
dcSaveTogHitEquip, //保存合击装备
dcLogout, // 玩家下线
// d-g
dcLoad,
dcLoadRole,
dcLoadItem,
dcLoadMail,
dcLoadVar, //加载角色变量
dcLoadStore, //加载商城
dcLoadTogHitEquip, //加载合击装备
dcLoadFriends = 35, // 读取本人的好友相关列表
dcUpdateFriend = 36, // 更新好友的信息
dcDelFriend = 37, // 删除好友信息
dcLoadMsg = 27, //读取用户的消息数据
dcDeleteMsg = 28, //删除某条消息
// todo下面是旧的以后整理删掉
//dcLoadQuest = 3, //装置任务数据
//dcSaveQuest = 4, //保存用户的任务数据(跨服战不保存)
//dcLoadSkill = 5, //装置技能数据
////dcSaveSkill = 6, //保存技能数据(跨服战不保存)
//dcLoadBagItem = 7, //装载背包物品
//dcSaveBagItem = 8, //保存背包物品数据 (跨服战要保存,因为要消耗药品)
//dcLoadEquipItem = 9, //装载装备物品
//dcSaveEquipItem = 10, //保存装备物品(跨服战不保存)
//dcLoadDepotItem = 11, //装载仓库物品 (跨服战不读取)
//dcSaveDepotItem = 12, //保存仓库物品13跨服战不保存
dcLoadBuff = 15, //加载角色buff的数据
dcSaveBuff = 16, //保存角色buff的数据跨服战保存有buff时间
dcAddMember = 23, //增加帮派成员
dcSaveActorGuild = 24, //保存个人帮派信息
dcDeleteMember = 25, //删除某个成员
dcLoadConsiTimeoutItem = 26, //读取已经下架的个人物品 (跨服战不读取)
dcLoadSpiritItemData = 29, // 读取宝物数据
dcSaveGemItemData = 30, // 保存宝物数据 (跨服战不保存)
dcLoadMountData = 31, //装载坐骑的数据
dcSaveMountData = 32, //保存坐骑的技能数据 (跨服战不保存)
dcSaveDmkjItem = 33, //保存抽奖的仓库物品 (跨服战不保存)
dcLoadDmkjItem = 34, //读取抽奖仓库的数据 (跨服战不读取)
dcUpdateFriendInfo = 38, //更新好友数据(下线时间)
dcUpdateFriendContact = 39, //更新最近联系时间(下线的时候)
dcSaveCale = 40, //保存副本统计数据(跨服战不读取)
dcLoadCale = 41, //读副本统计数据
dcLoadFbCountData = 42, // 读取每天进入副本次数数据(跨服战不读取)
dcSaveFbCountData = 43, // 保存每天进入副本次数数据
// 剧情动画
dcLoadPlotData = 48, //(跨服战不读取)
dcSavePlotData = 49, // 这两个已无用
//dcLoadMiscStruct = 50, // 读取杂七杂八数据 (跨服战不读取)
//dcSaveMiscStruct = 51, // 保存杂七杂八数据
// 竞技场
dcLoadFightLog = 55, // 读取PK记录 (跨服战不读取)
dcAddFightLog = 56, // 添加一条PK记录
dcSlaveAll = 57, // 苦工系统相关的数据保存,由脚本处理 (取消)
dcDelFightLog = 58, // 删除一条PK记录
// dcLoadMail = 59, //读取用户的邮件数据 (跨服战不读取)
dcDeleteMail = 60, //删除邮件
dcUpdateMailStatus = 61, //更新邮件状态
dcDeleteMailFile = 62, //删除邮件附件
dcGetActorIdFromActroName = 63, //根据玩家名字获取玩家ID
dcSaveEntrustItem = 64, //保存副本委托的仓库物品 (跨服战不读取)
dcLoadEntrustItem = 65, //读取副本委托仓库的数据
dcSaveActorMisc = 68, // 保存杂七杂八的数据
dcLoadActorMisc = 69, // 读取杂七杂八的数据
dcSavePetCrossItem = 70, //保存宠物闯关仓库(珍宝囊)(跨服战不保存)
dcLoadPetCrossItem = 71, //读取宠物闯关仓库(珍宝囊)的数据(跨服战不读取)
dcResetCrossPos = 80, // 重置跨服位置
dcLoadCrossVar = 81, //加载角色跨服战变量
dcSaveCrossVar = 82, //保存角色跨服战变量
dcLoadSkillMiji = 83, //读取技能秘籍数据
dcSaveSkillMiji = 84, //保存秘籍数据(跨服战不保存)
dcSaveTongTianTaStoreItem = 85, //保存通天塔仓库(跨服战不保存)
dcLoadTongTianTaStoreItem = 86, //读取通天塔仓库(跨服战不读取)
dcSaveWing = 87, //保存翅膀
dcLoadWing = 88, //读取翅膀
//宠物相关
//dcLoadAllPet = 96, // 加载所有宠物
//dcDeletePet = 97, // 删除宠物
dcLoadPetBase = 98, // 加载宠物基础数据
dcSavePetBase = 99, // 更新宠物
dcPetSkill = 100, // 宠物技能相关
//dcLoadPetGotType = 101, // 读取宠物的历史记录(跨服战不读取)
//dcAddPetGotType = 102, // 增加宠物的历史记录(跨服战不保存)
dcPetLoadEquip = 103, // 加载宠物装备
dcPetSaveEquip = 104, // 保存宠物装备
dcClearActorDbCache = 105, //清空玩家的缓存
//铭刻相关
dcAddEqSign = 106,//新增铭刻信息
dcInheritEqSign = 107,//继承替换铭刻信息
dcGetEqSignList = 108,//获取某装备上的铭刻信息
dcSaveOnceTime = 111, // 设置保存一次的时间
dcSaveRankVar = 112, // 保存排行榜相关数据
dcSetDataValid = 115, // 设置有效性标识
dcEnableCheckValid = 116, // 是否启用检查数据有效性
dcLoadActorGuild = 117, //读取角色帮派信息
dcSaveMarryInfo = 118, //保存结婚信息
dcLoadMarryInfo = 119, //加载结婚信息
dcOfflineLogout = 120, //下线时,对方不在线,写入相关数据
dcOfflineDivorce = 121, //离婚时,对方不在线,写入相关数据
dcSaveCsWarVar = 122, //保存角色跨服专用变量
dcLoadCsWarVar = 123, //加载角色跨服专用变量
dcActorCacheSave = 124,
dcActorCacheLoad = 125,
};
enum ConsignmentSysId
{
dcLoadConsignment = 1, //读取所有的寄卖物品信息
dcSaveConsignmentItem, //保存寄卖物品,包括删除和添加
dcConsignmentCount, // 寄卖物品总数
};
enum GuildMgrId
{
dcLoadGuildList = 1, // 帮派组件读入所有帮派的数据
dcLoadGuildDetail, // 帮派的详细数据
dcAddGuild, // 增加帮派
dcDeleteGuild, // 解散帮派
dcSaveGuild, // 保存帮派的信息
dcLoadGuildMgrData, // 读取帮派名称列表等
dcLoadGuildDepot, // 读取仙宗仓库物品信息
dcSaveGuildDepot, // 保存仙宗仓库物品信息
dcLoadBeastLog, // 读取帮派神兽记录
dcAddBeastLog, // 添加帮派神兽记录
dcDeleteBeastLog, // 删除帮派神兽记录
dcLoadGuildLog, // 读取仙宗事件
dcAddGuildLog, // 添加仙宗事件
dcDelGuildLog, // 删除仙宗事件
dcLoadOneGuild, // 加载一个帮派的数据
dcGuildCount, // 帮派数量
dcSaveGuildVar, // 保存帮派数据(静态变量)
dcLoadGuildVar, // 读取帮派数据(静态变量)
dcSaveGuildChat, // 保存公会聊天记录
dcLoadGuildStore, // 读取公会商店记录
dcSaveGuildStore, // 保存公会商店记录
};
enum AuctionId
{
dcAuctionAdd = 1,
dcAuctionDel,
dcAuctionUpdate,
};
enum TopTitleId
{
dcLoadRank = 1, //读取有关头衔的排行榜数据
dcLoadRankUser = 2, // 用户详细数据
dcLoadRankPet = 3, //宠物详细数据
dcRankUserCount, // 用户详细数据的数量
};
enum MsgMgrId
{
dcAddMsg = 1, //增加用户一条信息
dcAddChat = 2, //聊天监控的信息
};
enum MailMgrId
{
dcAddMail = 1, //增加用户一条邮件
dcAddMailByActorName, // 增加用户一条信息(通过玩家名称)
dcAddMailByAccountName, // 增加用户一条信息通过open id
};
enum GlobalMgr
{
dcLoadBossKiller = 1, // 保存世界boss的击杀者
dcSaveBossKiller,
dcLoadMaster, // 读取天元之主装备信息
dcSaveMaster, // 保存天元之主装备信息
dcGmCmd, // 发送gm命令 暂时改到lua里注册以后整理消息时要改
//dcAllActorBI, // 发送用户数据到BI系统已无用
dcCheckVer, // 检查gameworld的版本是否与dbserver一致
dcLoadMarry, // 读取全服仙侣数据
dcAddMarry, // 增加一个结婚记录
dcBattleFlag, // 表示这个连接是否从战斗服发起如果是则不读取gmcmd表的数据
dcAddQuestion = 10, //增加一条问题
dcLoadQuestions, //读取玩家所有的问题
dcLoadQuestion, //读取某一条问题
dcUpdateQuestion, //更新问题 已阅读
dcAddBug = 14, //增加一条bug
dcLoadGoldRank, //读取神榜内容
dcAddGameServerInfo, //添加一条gameworld相关信息
};
enum FightRankId
{
dcLoadFightRank = 1, // 读取竞技场排行榜
dcSaveFightRank, // 保存竞技场排行榜
};
enum SysVarMgrId
{
dcAddSysVar = 1,
dcLoadSysVar,
dcUpdateSysVar,
dcSysVarCount,
};
enum configType
{
ctLoadGiftItem = 1, //读取礼包作为物品的数据
ctLoadGiftConfig = 2, //读取礼包奖励数据
};
// 通信的错误码定义
enum tagResultError
{
reSucc = 0,
reDbErr, //数据库执行错误
reNoActor, //没有该角色的属性信息
reSaveErr, //保存属性失败
reNoLoad, //还没有读入数据
reDbNotConnected, //DB连接不上
reParamError, //参数错误
reNameError, //名字不合法
reNameInUse, //名字被使用
reTimeOut, //操作超时
reInterErr, //内部错误
};
// 战队消息ID
enum WarTeamSysId
{
dcLoadWarTeam = 0,
dcAddWarTeam,
dcDelWarTeam,
dcUpdateWarTeam,
dcLoadWarTeamMember,
dcAddWarTeamMember,
dcDelWarTeamMember,
dcUpdateWarTeamMember,
dcLoadOneWarTeam, // 获取一个战队的信息
dcWarTeamCount, // 本服需要加载的战队数量
};
enum TxApiMsg
{
// 充值返回
sFeeCallBack = 1,
// 腾讯api返回
sTxApiMsg = 2,
// 更新用户身份证号码
sUpdateIdentity = 4,
// 关闭或开启赌博系统
sCloseGamble = 5,
// 用户充值获取token
sChargeToken = 6,
// 开通黄钻等获取token
sGetToken = 7,
//增值序列号
sAddValueCard = 8,
// 查询增值卡
sQueryAddValueCard = 9,
// 查询元宝数量
sQueryYuanbaoCount = 10,
// 提取元宝
sWithdrawYuanbao = 11,
// 发送登陆的key
sLoginKey = 12,
};
enum CommonDBMsg
{
dcDBExec = 1, // 执行预定义
};
enum TradingMgrId
{
dcAddTrading = 1,
dcUpdateTrading,
dcDelTrading,
};
}
namespace AsyncOperatorCode
{
enum tagAsyncOpError
{
soeSucc = 0, // 成功
soeDBErr, // db执行错误或者db无法连接
soeNoCardInfo, // 不存在此卡信息
soeTimeExpired, // 查询超时
};
}
// gameworld之间通信的协议
namespace GameWorldProto
{
enum GwP
{
gpRegReq = 1, // 注册消息发送最基本的信息比如serverid
gpRegResp = 2,
gpKeyReq = 3, // 发送key的请求和回复
gpKeyResp = 4,
gpUserLogin = 5, // 广播玩家登陆的消息
gpBatchOnline = 6, // 同步在线玩家的信息
gpUserExit = 7, // 玩家下线消息
gpCloseUser = 8, // 踢玩家下线
gpGateway = 9, // 同步网关的信息
gpTtData = 10, // 转传协议
gpSsData = 11, // C++代码内,服务器之间的游戏逻辑消息
gpLfData = 12, // 连服相关系统信息
// 除此之外的全是游戏逻辑相关的信息
gpCommonMsg, // 游戏逻辑相关的消息
gpCrossRelogin, // 通知跨服服务器玩家重复登录
};
enum LfSysType {
lsDefault = 0,
lsGuild,
lsRank,
};
enum SSP
{
stBroadCast, //广播
stRankList, //发送排行榜列表
stUserLogin, //玩家登录
stUserLogout, //玩家登出
stBatchOnline, //批量上线(同步玩家登录信息)
//stRecvMail, //通知玩家收邮件 todo lua实现
stKickUser, //踢掉连服的玩家
//stRecvOfflineMsg, //通知玩家收离线消息 todo lua实现
stNormalMax = 100, //后面开始是脚本处理的消息
};
enum LfGuildCmd {
lcGuildList, // 更新仙宗列表
lcGuildUnion, // 仙宗结盟
lcGuildDelUnion, //
lcCreateGuild, // 创建仙宗
lcDelGuild, // 删除仙宗
lcUpdateGuild, // 更新仙宗信息
lcDelGuildMem, //
lcAddGuildMem, //
lcGuildBroadCast, // 仙宗广播
lcUpGuildMemInfo, //
lcGuildOnline, // 普通服通知仙宗在线状态
lcGuildLeaderInfo, //发送帮主的一些信息
lcAddItemToDepot, //增加一个道具到仓库
lcAddGuildLog, //增加一条帮派见闻
lcSendFightVal, //发送帮派战力
lcChangePos, //改变玩家职位
lcDepotAvailible, //帮派仓库剩余位置
lcImpeach, //弹劾
};
enum LfRankCmd {
lcRankList = 0, // 发送排行榜列表
lcRankTitle = 1, //发送通知修改排行榜称号
};
};
// gameworld 和 centerserver 之间的通信协议
namespace CenterProto
{
enum CWP
{
cwComm = 1, // 直接转发的的数据包
cwActorOnline = 2, //在某服在线或不在线
cwActorServer = 3, //根据actorid发送到actorid所在服务器
cwActorServerInfo = 4, //玩家在哪个服务器
};
struct ActorOnline
{
int actorid_;
int sid_;
inline bool operator != (const ActorOnline& data) const
{
return actorid_ != data.actorid_;
}
inline bool operator > (const ActorOnline& data) const
{
return actorid_ > data.actorid_;
}
inline bool operator < (const ActorOnline& data) const
{
return actorid_ < data.actorid_;
}
};
}
}

10
Gateway/common/common.h Normal file
View File

@@ -0,0 +1,10 @@
#include <cstring>
#include <stdint.h>
#include <vector>
#include <list>
#include <map>
#include "server_def.h"
#include "share_util.h"
#include "data_packet.hpp"
#include "container/static_hash_table.h"

View File

@@ -0,0 +1,57 @@
#ifndef _CONFIG_DATA_DEF_H_
#define _CONFIG_DATA_DEF_H_
//数据读取的时候的一些公共的数据结构
//这个结构体存游戏中任务数据的一些数组
template <class T>
struct DataList
{
DataList<T>()
{
data_ = NULL;
count_ = 0;
}
T* data_;
int count_;
//inline operator T* () const { return data_; }
inline T* GetDataPtr(int nIndex)
{
if (data_ && nIndex >= 0 && nIndex < count_)
{
return data_ + nIndex;
}
else
{
return NULL;
}
}
};
template <class T, int MAX_NUM = 16>
struct StaticDataList
{
StaticDataList<T, MAX_NUM>()
{
count_ = 0;
}
~StaticDataList(){
count_ = 0;
}
T data_[MAX_NUM];
int count_;
//inline operator T* () const { return data_; }
inline T* GetDataPtr(int nIndex)
{
if (nIndex >= 0 && nIndex < count_ && nIndex < MAX_NUM)
{
return &data_[nIndex];
}
else
{
return NULL;
}
}
};
#endif

View File

@@ -0,0 +1,76 @@
#ifndef _GEM_DEF_H_
#define _GEM_DEF_H_
#include "common.h"
#define MAX_SPIRIT_SKILL 8
#define MAX_SPIRIT_COUNT 5
#define MAX_SPIRIT_SLOT 8
// 仙魂对象
// 仙魂项的属性
#pragma pack( push, 1 )
struct SoulPropData {
uint8_t type; // 种类
uint8_t quality; // 品质
uint8_t level; // 等级
int expr; // 灵力
uint8_t lock; //是否绑定
};
struct SpiritSoul
{
enum Type { tGem = 0, tHunt = 1 }; // 法宝界面或炼魂界面的仙魂
int id; // 系统给仙魂分配的ID
SoulPropData prop_data; // 仙魂属性
};
// 法宝基础属性
struct GemInfo
{
int state; // 法宝境界
int level; // 法宝等级
int expr; // 法宝经验
int score; // 法宝评分
};
struct GemGuard
{
int type; //灵侍类型
int level; //灵侍等级
int expr; //灵侍经验
GemGuard()
{
type = 0;
level = 0;
expr = 0;
}
GemGuard(int type, int level = 1, int expr = 0)
{
this->type = type;
this->level = level;
this->expr = expr;
}
};
struct SpiritRankData
{
int level_; //觉醒等级
int model_id_; //精灵外观
int max_slot_cnt_; //能量槽位
int spirit_cnt_; //元素个数
int slot_cnt_[MAX_SPIRIT_COUNT];
SpiritSoul spirit_[MAX_SPIRIT_COUNT][MAX_SPIRIT_SLOT];
int skill_cnt_; //技能个数
BaseSkillData skill_list_[MAX_SPIRIT_SKILL];
};
#pragma pack( pop )
#endif

View File

@@ -0,0 +1,164 @@
#ifndef _PROPERTY_ID_DEF_H_
#define _PROPERTY_ID_DEF_H_
///下面这里定义的是实体的属性的ID脚本里需要用到,通过实体的id可以获取实体的属性
//tolua_begin
//下面这些是属性的偏移
enum enPropEntity
{
P_ID = 0, // 实体的id
P_POS_X , // 位置 posx
P_POS_Y , // 位置pos y
P_MODELID, // 实体的模型ID
P_ICON, // 头像ID
P_DIR, // 实体的朝向
P_MAX_ENTITY,
};
enum enPropCreature
{
P_LEVEL = P_MAX_ENTITY, // 等级
P_HP , //血
P_MP , //蓝
P_SPEED, //移动1格需要的时间单位ms
P_MAXHP, //最大血,也就是生命
P_MAXMP,//最大蓝,也就是内力
P_OUT_ATTACK, //外功攻击
P_OUT_DEFENCE,//外功防御
P_DEFCRITICALSTRIKES,//抗爆击值
P_ALL_ATTACK, // 所有攻击力
P_SUB_DEF, // 无视防御
P_IN_ATTACK,//内功攻击
P_IN_DEFENCE,//内功防御
P_CRITICALSTRIKES, // 爆击值
P_DODGERATE, // 闪避值
P_HITRATE, // 命中值
P_ATTACK_ADD, // 伤害追加
P_HP_RENEW,//HP恢复
P_MP_RENEW,//MP恢复
P_ATTACK_SPEED, //攻击速度
P_IN_ATTACK_DAMAGE_ADD, // 承受内功伤害的数值提高
P_OUT_ATTACK_DAMAGE_ADD, // 承受外功伤害的数值提高
P_THUNDER_ATTACK, //雷攻
P_THUNDER_DEFENCE, //雷抗
P_POISON_ATTACK, //毒攻
P_POISON_DEFENCE, //毒抗
P_ICE_ATTACK, //冰攻
P_ICE_DEFENCE, //冰抗
P_FIRE_ATTACK, //火攻
P_FIRE_DEFENCE, //火抗
P_STATE, //生物的状态,死亡,打坐等等
P_BASE_MAXHP, //基础的最大血,等级带来的MaxHp,不包括buff装备等附加的
P_BASE_MAXMP, //基础的最大蓝,等级带来的MaxMp,不包括buff装备等附加的
P_STAND_POINT, //立场立场不为0且不相等的可以互相攻击
P_RESEVS0, //保留字段
P_RESEVS1, //保留字段
P_MAX_CREATURE, //
};
//怪物的
enum enPropMonster
{
P_MONSTER_START = P_MAX_CREATURE,
P_BORNPOINT = P_MONSTER_START, // 怪物的出生点(无用)
P_LEVEL_DIFF, // 无用
//// 以下属性是为了给宠物的
P_PET_TITLE, // 宠物的称号低2位是等阶称号高2位是兽阶称号如果不是宠物则为0
P_PET_COLOR,
P_PET_RANK_TITLE,
P_MAX_MONSTER,
};
enum enPropActor
{
P_WEAPON = P_MAX_CREATURE, //武器的外观属性
P_MOUNT, //坐骑的外观属性
P_DIZZY_RATE11, // 低2为攻击打出晕眩的几率,高2位是烦晕眩几率(取消
P_DIZZY_TIME1, // 攻击打出晕眩的时间(取消)
P_HP_STORE, //hp存量
P_MP_STORE, //宠物的hp存量(旧:mp存量)
P_SPIRIT, //精灵样式
P_PK_MOD, //玩家的PK模式
P_STRONG_EFFECT, //强化特效
P_WING, // 翅膀特效
P_STAGE_EFFECT, //品质特效
P_PET_HP_STORE, // 宠物药包
PROP_ACTOR_XIUWEI_RENEW_RATE, //玩家的修为的恢复速度(取消)
P_SEX , //性别
P_VOCATION , //职业
P_EXP , //这个多1个字节,uint64的
P_PK_VALUE = P_EXP + 2, //玩家的pk值(杀戮值)(已无用)
P_BAG_GRID, //背包的格子数量
P_WEEK_CHARM, // 周魅力值
P_BIND_COIN, //绑定金钱
P_COIN, //非绑定金钱
P_BIND_YB, //绑定元宝
P_YB, //非绑定元宝
P_SHENGWANG, //玩家的声望
P_CHARM, //魅力值,男的叫帅气值,女的叫魅力值
P_SPIRIT_SLOT, //宝物开通的槽位的数目(貌似没用)
P_RENOWN, //历练
P_GUILD_ID , //帮派的ID
P_TEAM_ID, //队伍的ID
P_SOCIAL,// 社会关系的mask是一些bit位合用的
P_GUILD_EXP, //帮会贡献度
P_LUCKY, //幸运值
P_SYS_OPEN, // 开启系统的开放情况
P_ROOT_EXP_POWER, // 灵气增长的倍率
P_CHANGE_MODEL, // 变身后的模型(不存盘)
PROP_BANGBANGTANG_EXP, ////棒棒糖经验的增长的速度(这功能应该没用了)
PROP_ACTOR_MAX_EXP, //玩家的最大经验64位的(貌似无用)
P_GIVE_YB = PROP_ACTOR_MAX_EXP + 2, //元宝中有多少是赠送的元宝
P_CRITICAL_STRIKE, //暴击的伤害百分比
P_EXP_RATE, //玩家经验的增长的速度默认是1倍的
P_DEPOT_GRID, // 仓库打开格子数量
P_ANGER, // 怒气值
P_ROOT_EXP, // 灵气值
P_ACHIEVEPOINT, //完成的成就个数(排行榜)
P_ZYCONT,//阵营的贡献度(不要直接修改!!! 调用Actor的接口ChangeZYCount进行修改)
P_QQ_VIP, // vip信息数据
P_WING_ID, // 翅膀id
P_WING_SCORE, // 翅膀评分
P_PET_SCORE, // 宠物评分
PROP_ACTOR_VIPFLAG, // VIP开通标记通过位掩码标记各种VIP类型。enVIPType定义着VIP类型分别对应0-2位掩码。(好像没用)
P_CAMP, //玩家的阵营 1逍遥2星尘3逸仙
P_PET_SLOT, //玩家开启的宠物槽位的数量(取消)
P_HONOR, //荣誉值
P_QING_YUAN, //情缘值
PROP_ACTOR_DUR_KILLTIMES, //连斩的次数(取消)
PROP_ACTOR_BASE_FIGHT, //今天获得的经验(取消)
P_FIGHT_VALUE, //战斗力
P_MAX_RENOWN, //玩家的最大的声望的数值
P_RECHARGE, // 玩家充值总金额
P_VIP_LEVEL, // 玩家的头衔,用于头衔系统按位表示玩家是否有这个头衔默认为0取消
P_BEAST_LEVEL, // 玩家所在帮派的仙宗神兽等级(取消这个放到PROP_FOOT_EFFECT)
P_FOOT_EFFECT, // 足迹
P_EQUIP_SCORE, //玩家的装备的总分
P_HAIR_MODEL, //时装帽外观
P_BUBBLE, // 气泡
P_ACTOR_STATE, //玩家的状态
P_JINGJIE_TITLE, //境界称号
P_ZHUMOBI, //诛魔币
P_MAX_ACTOR,
};
//tolua_end
#endif

View File

@@ -0,0 +1,306 @@
#ifndef _PROPERTY_SET_H_
#define _PROPERTY_SET_H_
#include "common.h"
#include "property_id_def.h"
#pragma pack(4)
// 暂时支持32*8个属性最大只能255个属性 因为个别地方用uint8_t表示属性的数量
static const unsigned int MAX_BYTE = 32;
static char s_forbit_mask[MAX_BYTE] = {};
class UpdateMask
{
public:
UpdateMask(): used_count_(0), mask_count_(0)
{
memset(lock_, 0, sizeof(lock_));
clear();
}
inline void clear()
{
memset(mask_, 0, sizeof(mask_));
used_count_ = 0;
mask_count_ = 0;
}
inline UpdateMask& operator &= (UpdateMask& mask)
{
int count = __max(used_count_, mask.count());
if (count == 0) return *this;
int max_count = 0;
unsigned char* s = mask;
for (int i = 0; i < count; ++i)
{
mask_[i] &= s[i];
if (mask_[i]) max_count = i + 1;
}
used_count_ = max_count;
mask_count_ = 0;
int total = used_count_ << 3;
for (int i = 0; i < total; ++i)
{
if (IsMask(i)) ++mask_count_;
}
return *this;
}
/*
*设置第nPos个int是否修改过
* nPos 第几个4字节
* flag flag=true表示修改过,否则去掉这个修改标记
*/
inline void SetMask(int pos/*, bool flag = true*/)
{
if (IsForbid(pos)) return; // 禁止更新
unsigned int bit_pos = pos & 7;
unsigned int byte_pos = pos >> 3;
if (byte_pos >= MAX_BYTE) return;
unsigned char value = 1 << bit_pos;
//if (flag)
{
if (!(mask_[byte_pos] & value)) ++mask_count_;
mask_[byte_pos] |= value;
}
//else
//{
// 如果原来就是maskedmask_count要减一
// if (mask_[byte_pos] & value){ assert(mask_count_ > 0);--mask_count_;}
// value = ~value;
// mask_[byte_pos] &= value;
//}
if (used_count_ <= byte_pos)
used_count_ = byte_pos + 1;
}
//第nPos个int是否修改过
inline bool IsMask(int pos)
{
unsigned int bit_pos = pos & 7;
unsigned int byte_pos = pos >> 3;
if (byte_pos >= MAX_BYTE) return false;
unsigned char value = 1 << bit_pos;
return mask_[byte_pos] & value ? true : false;
}
inline unsigned int count()
{
return used_count_;
}
inline unsigned int MaskCount()
{
return mask_count_;
}
inline operator unsigned char* ()
{
return mask_;
}
static void SetArrayBit(char* arr, int pos, bool flag)
{
unsigned int bit_pos = pos & 7;
unsigned int byte_pos = pos >> 3;
if (byte_pos >= MAX_BYTE) return;
unsigned char value = 1 << bit_pos;
if (flag) //让其成立
{
arr[byte_pos] |= value;
}
else
{
value = ~value; //取反
arr[byte_pos] &= value; //按位与
}
}
static bool IsArrayBit(char* arr, int pos)
{
unsigned int bit_pos = pos & 7;
unsigned int byte_pos = pos >> 3;
if (byte_pos >= MAX_BYTE) return false;
unsigned char value = 1 << bit_pos;
return arr[byte_pos] & value ? true : false;
}
//设置禁止更新的属性的位
static void SetForbid(int pos, bool flag)
{
SetArrayBit(s_forbit_mask, pos, flag);
}
//某个位置是否禁止更新
inline bool IsForbid(int pos)
{
return IsArrayBit(s_forbit_mask, pos);
}
inline bool IsLock(int pos)
{
return IsArrayBit(lock_, pos);
}
void Lock(int pos)
{
SetArrayBit(lock_, pos, true);
}
void UnLock(int pos)
{
SetArrayBit(lock_, pos, false);
}
static void Init()
{
memset(s_forbit_mask, 0 , sizeof(s_forbit_mask));
}
private:
unsigned char mask_[MAX_BYTE]; //这个是mask的存储地方
unsigned int used_count_; //已经使用的字节数
unsigned int mask_count_;
char lock_[MAX_BYTE]; // 锁定属性值,不允许设置新值
};
//实体属性集合,可以是各种数据,带有一个mask纪录第几个int的值修改过
class PropertySet:
public UpdateMask
{
public:
PropertySet() {}
template<typename T>
inline bool set(int pid, const T& value)
{
if (IsLock(pid)) return false;
T* pos = (T*)ptr(pid);
if (*pos == value) return false; //没改变
int offset = (int)((char*)pos - (char*)this - sizeof(UpdateMask)); //偏移了多少字节
if (offset < 0) return false;
*pos = value; //设置值
if (offset > 0) offset = offset >> 2;
int size = sizeof(T);
size = __max(size >> 2, 1); //多少个4字节
for (int i = 0; i < size; ++i)
{
SetMask(offset + i);
}
return true;
}
//获取属性集第nPos个int的指针
inline const char* ptr(int pos) const
{
const char* ptr = (const char*)this + sizeof(UpdateMask) + (pos << 2);
return ptr;
}
// 获取数据的首地址
inline const char* ptr() const
{
return (const char*)this + sizeof(UpdateMask);
}
template < class T>
inline T GetProperty(int pos) const
{
return *(T*)this->ptr(pos);
}
template < class T>
inline void SetProperty(int pos, const T& value)
{
if (IsLock(pos)) return;
T oldValue = GetProperty<T>(pos);
if (oldValue == value) return;
this->set(pos, value);
}
// dtrue表示读取8字节否则默认都是4字节intfloat类型的长度
inline void set(int pos, PropertySet* set, bool d)
{
memcpy((char*)(this->ptr(pos)), set->ptr(pos), d ? 8 : 4);
}
};
class EntityProperty:
public PropertySet
{
public:
int data_[P_MAX_ENTITY];
EntityProperty()
{
memset(this, 0, sizeof(EntityProperty));
}
};
STATIC_ASSERT((P_MAX_ENTITY - P_ID) == (sizeof(EntityProperty) - sizeof(PropertySet)) / sizeof(int));
//玩家的属性集,包括 玩家的db数据,1级属性数据
class ActorProperty:
public PropertySet
{
public:
int data_[P_MAX_ACTOR];
ActorProperty()
{
memset(this, 0, sizeof(ActorProperty));
}
};
// 如果修改过ActorProperty结构把这个值相应的修改成新的PROP_MAX_ACTOR的值同时知会客户端程序
STATIC_ASSERT((sizeof(ActorProperty) - sizeof(UpdateMask)) / sizeof(int) == P_MAX_ACTOR);
//怪物的属性集合
class MonsterProperty:
public PropertySet
{
public:
int data_[P_MAX_MONSTER];
MonsterProperty()
{
memset(this, 0, sizeof(MonsterProperty));
}
};
STATIC_ASSERT((sizeof(MonsterProperty) - sizeof(UpdateMask)) / sizeof(int) == P_MAX_MONSTER);
#pragma pack()
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
#ifndef _ACHIEVE_DATA_H_
#define _ACHIEVE_DATA_H_
#include "common.h"
#include "skill_data.h"
#include "common/datalist.h"
// 称号的存储的BYTE数量
#define MAX_TITLE_DATA_SIZE 32
// 成就存储一共占用的字节数目
#define MAX_ACHIEVE_DATA_SIZE 256
// 成就勋章数量上限
#define MAX_MEDALS_COUNT 256
#pragma once
#pragma pack (push, 1)
//成就的条件
struct ACHIEVECONDITION
{
uint16_t eventId_; //成就事件ID
int count_; //事件的数量
};
struct ACHIEVEMEDAL
{
uint8_t id_; //成就勋章的ID
unsigned int reach_time_; //获取日期
};
struct AchieveRankData
{
int medal_cnt; //勋章个数
ACHIEVEMEDAL medal_list_[MAX_MEDALS_COUNT];
AchieveRankData() : medal_cnt(0){}
};
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,56 @@
#pragma once
enum DBCacheType
{
DBCacheType_Undefined = -1, // 返回错误类型
DBCacheType_ActorBasic = 0, // 角色基础数据
DBCacheType_RoleData, // 子角色数据
DBCacheType_ScriptData,
DBCacheType_ItemBag, // 道具包
DBCacheType_EquipBag, // 装备包
DBCacheType_Mail, // 邮件
DBCacheType_Store, // 商城
DBCacheType_Depot, // 仓库
DBCacheType_Guild, // 公会
DBCacheType_TogHitEquip, // 合击装备
DBCacheType_CsScriptData, //跨服的lua
DBCacheType_ActorCache, //跨服缓冲用
DBCacheType_Max,
};
// 角色Cache数据类型 (旧的 弃用 暂时先留着 工作量太大)
enum enActorCacheDataType
{
enCT_ActorBasicData, // 角色基本数据
enCT_BagItemData, // 角色背包数据
enCT_EquipItemData, // 角色装备数据
enCT_DepotItemData, // 角色仓库数据
enCT_SkillData, // 技能数据
enCT_QuestData, // 任务数据
enCT_GuildData, // 公会数据
enCT_MiscData, // 杂项数据
enCT_ScriptData, // 脚本二进制数据
enCT_GemData, // 宝物数据
enCT_MountData, // 宠物数据
enCT_DmkjItemData, //盗梦空间仓库
enCT_WingData, //翅膀数据
enCT_BuffData, //buff数据
enCT_AchieveData, // 成就
enCT_CaleData, //副本统计数据
enCT_FbCountData, //每天进入副本次数
enCT_PlotData, // 剧情(已无用)
enCT_MiscStruct, // 杂七杂八数据(已无用)
enCT_PetSkill, // 宠物技能
enCT_EntrustItemData, // 副本委托仓库
enCT_PetItemData, //宠物装备
enCT_PetCrossItem, //宠物闯关仓库
enCT_CrossScriptData, // 跨服战脚本数据
enCT_TongTianTaData, //通天塔数据
enCT_MijiItem, //秘籍数据
enCT_PetBase, //宠物系统
enCT_MarryBase, //婚姻系统
enCT_Max, // 最大角色Cache数据类型
};

View File

@@ -0,0 +1,274 @@
#pragma once
#ifndef _ACTOR_DB_DATA_H_
#define _ACTOR_DB_DATA_H_
#include "common.h"
#include "common/datalist.h"
#include "common/property_set.h"
#pragma pack(push,4)
/*
玩家需要存盘的数据结构体
*/
using namespace SrvDef;
//tolua_begin
struct ActorBasicData
{
unsigned int account_id; //账户的ID
//ACCOUNT account_name; //账户名字
char account_name[ACCOUNT_LENGTH]; //账户名字
int actor_id; //角色id
//ACTORNAME actor_name; //名字
char actor_name[ACTOR_NAME_BUFF_LENGTH]; //名字
unsigned int server_idnex;
unsigned char job; // 第一个角色职业
unsigned char sex; // 第一个角色性别
unsigned int level;
unsigned int exp;
long long int fb_uid; //副本的uid
unsigned int fb_scene_id; //副本内的场景id
unsigned int create_time; //创建的时间
unsigned int last_online_time; //最后在线时间
unsigned long long last_login_ip;//上次登录的ip,还没支持
unsigned int total_online; //总的在线时长
unsigned int daily_online; //单日在线时长
unsigned int bag_grid; // 背包开启数量
long long int gold;
long long int yuanbao;
long long int total_power; // 总战力
long long int rank_power; //用于排行榜的战力
unsigned int recharge; // 充值元宝数
unsigned int paid; // 消费元宝数
unsigned int chapter_level; // 所在关卡数 同时用于选择静态场景所在的场景
unsigned int vip_level; // vip等级
int essence; // 精魄
int zhuansheng_lv; // 转生等级
int zhuansheng_exp; // 转生修为
unsigned char monthcard; //0为没购买1,为没过期,2为过期
int tianti_level; //天梯级别
int tianti_dan; //天梯段位
int tianti_win_count; //天梯净胜
int tianti_week_refres; //天梯周刷新
long long int total_wing_power; //翅膀总战力
long long int warrior_power; //战士战力
long long int mage_power; //法师战力
long long int taoistpriest_power; //道士战力
int train_level; //神工(爵位)等级
int train_exp; //神工(爵位)经验
int total_stone_level; //宝石(精炼)总等级
int total_zhuling_level;//铸造总等级
int guild_id_; //公会ID
char guild_name_[32];//工会名
int zhan_ling_star; //
int zhan_ling_stage; //
int total_loongsoul_level;
int prestige_exp; //威望值
long long int feats; // 功勋
unsigned int ex_ring_lv[8];//特戒等级,最高位为1时候出战
long long int shatter; //符文碎片
long long int spcshatter; //特殊符文碎片
unsigned int knighthood_lv;//勋章等级
long long int togeatter;//合击碎片
int total_wing_lv; //翅膀总阶级
long long int total_tujian_power;//图鉴总战力
long long int total_equip_power;//装备总评分
long long int togeatterhigh;//高级合击碎片
unsigned char privilege_monthcard; //特权月卡, 未购买或已过期为0,1为没过期
int reincarnate_lv; // 轮回等级
int reincarnate_exp; // 轮回修为
long long int dianquan;//点券
int quota; //交易额度
};
inline ActorBasicData* toActorBasicData(void* data) { return (ActorBasicData*)data; }
//tolua_end
struct ActorCsData {
unsigned int actor_id; //角色id
// 跨服数据
unsigned long long cw_fbhdl_sid_; // 跨服战的位置信息,低4位是fuben的handle高4位是战斗服的sid
unsigned long long cw_scene_xy_; // 跨服战的位置信息,低4位是场景id高4位中的低高两位分别是xy
unsigned long long cw_static_pos_; // 进入副本前在普通场景的位置低4位是场景id高4位中的低高两位分别是xy
ActorCsData() {
memset(this, 0, sizeof(ActorCsData));
}
};
#pragma pack(pop)
inline void ReadActorBasicData(ActorBasicData& actor_data, MYSQL_ROW &pRow, unsigned long *fieldLength)
{
/*select level, exp, baggridcount, gold, yuanbao, totalpower, paid, fbhandle, sceneid,
createtime, lastlogouttime, totalonline, dailyonline
from actors
where actorid = nactorid and(status & 2) = 2;
*/
#define GetRowInt(i, data) sscanf(pRow[i], "%d", &(data))
#define GetRowUChar(i, data) int temp##i; sscanf(pRow[i], "%d", &(temp##i)); data = temp##i;
#define GetRowLInt(i, data) sscanf(pRow[i], "%lld", &(data))
#define GetRowString(i, data) sscanf(pRow[i], "%s", (data))
#define GetRowData(i,data) if(pRow[i]!=NULL) memcpy(&(data),pRow[i],fieldLength[i])
#ifdef _MSC_VER
#pragma message("todo 封装数据库流程")
#endif
GetRowInt(0, actor_data.account_id);
GetRowString(1, actor_data.account_name);
GetRowInt(2, actor_data.actor_id);
GetRowString(3, actor_data.actor_name);
GetRowUChar(4, actor_data.job);
GetRowUChar(5, actor_data.sex);
//GetRowInt(6, actor_data.status);
GetRowInt(7, actor_data.level);
GetRowInt(8, actor_data.exp);
GetRowInt(9, actor_data.server_idnex);
//GetRowInt(10, actor_data.create_time);
tm t;
memset(&t, 0, sizeof(t));
sscanf(pRow[10], "%d-%d-%d %d:%d:%d",
&t.tm_year,
&t.tm_mon,
&t.tm_mday,
&t.tm_hour,
&t.tm_min,
&t.tm_sec
);
t.tm_year -= 1900;
t.tm_mon -= 1;
actor_data.create_time = (unsigned int)mktime(&t);
//GetRowInt(11, actor_data.updatetime);
GetRowInt(12, actor_data.last_online_time);
GetRowLInt(13, actor_data.last_login_ip);
GetRowInt(14, actor_data.bag_grid);
GetRowLInt(15, actor_data.gold);
GetRowLInt(16, actor_data.yuanbao);
GetRowLInt(17, actor_data.total_power);
GetRowInt(18, actor_data.recharge);
GetRowInt(19, actor_data.paid);
GetRowLInt(20, actor_data.fb_uid);
GetRowInt(21, actor_data.fb_scene_id);
GetRowInt(22, actor_data.total_online);
GetRowInt(23, actor_data.daily_online);
GetRowInt(24, actor_data.chapter_level);
GetRowInt(25, actor_data.vip_level);
GetRowInt(26, actor_data.essence);
GetRowInt(27, actor_data.zhuansheng_lv);
GetRowInt(28, actor_data.zhuansheng_exp);
GetRowUChar(29, actor_data.monthcard);
GetRowInt(30, actor_data.tianti_level);
GetRowInt(31, actor_data.tianti_dan);
GetRowInt(32, actor_data.tianti_win_count);
GetRowInt(33, actor_data.tianti_week_refres);
GetRowLInt(34, actor_data.total_wing_power);
GetRowLInt(35, actor_data.warrior_power);
GetRowLInt(36, actor_data.mage_power);
GetRowLInt(37, actor_data.taoistpriest_power);
GetRowInt(38, actor_data.train_level);
GetRowInt(39, actor_data.train_exp);
GetRowInt(40, actor_data.total_stone_level);
GetRowInt(41, actor_data.guild_id_);
GetRowInt(42, actor_data.zhan_ling_star);
GetRowInt(43, actor_data.zhan_ling_stage);
GetRowInt(44, actor_data.total_loongsoul_level);
GetRowLInt(45, actor_data.feats);
GetRowData(46, actor_data.ex_ring_lv);
GetRowLInt(47, actor_data.shatter);
GetRowLInt(48, actor_data.spcshatter);
GetRowInt(49, actor_data.knighthood_lv);
GetRowLInt(50, actor_data.togeatter);
GetRowLInt(51, actor_data.rank_power);
GetRowInt(52, actor_data.total_wing_lv);
GetRowLInt(53, actor_data.total_tujian_power);
GetRowLInt(54, actor_data.total_equip_power);
GetRowLInt(55, actor_data.togeatterhigh);
GetRowInt(56, actor_data.total_zhuling_level);
GetRowInt(57, actor_data.prestige_exp);
GetRowInt(58, actor_data.reincarnate_lv);
GetRowInt(59, actor_data.reincarnate_exp);
GetRowLInt(60, actor_data.dianquan);
GetRowInt(61, actor_data.quota);
//中间有两个 appid和pfid
GetRowString(64, actor_data.guild_name_);
}
#endif
/*
//这个是以前斩仙和db通信的包
typedef struct tagActorDbData:
ActorProperty
{
ACTORNAME name; //名字
unsigned nFbHandle; //副本的句柄如果是0表示是普通的场景
unsigned nScenceID; //场景id
unsigned nEnterFbScenceID;
int nEnterFbPos; //X 和y放在了一起
unsigned int nCreateTime; //创建的时间
unsigned long long lLastLoginIp ;//上次登录的ip,还没支持
unsigned int nLastLogoutTime; //上次的下线时间,这个表示上次在逻辑服务器的下线时间,minidate格式
unsigned int nFbTeamId; // 个人积分(无用)
ACCOUNT accountName; //账户名字
unsigned int achieveTime; //成就达成时间
unsigned int nAccountId; //账户的ID
int64_t csrevivepoint; //普通场景的复活点是场景id,x,y的组合
int64_t fbrevivepoint; //副本场景的复活点是场景id,x,y的组合
int64_t cityrevivepoint; //城镇的复活点是场景id,x,y的组合
int free_baptize_; // 免费洗炼的次数
int one_key_time_; // 剩余一键征友的次数
int mount_score_; // 坐骑评分
int friend_cong_; // 好友祝贺的数据
int reserve_data_; // 保留字段数据,可使用
unsigned int spirit_score_; //玩家的精灵的总分
int lianfuTeamId; //连服队伍id
// 跨服数据
unsigned long long cw_fbhdl_sid_; // 跨服战的位置信息,低4位是fuben的handle高4位是战斗服的sid
unsigned long long cw_scene_xy_; // 跨服战的位置信息,低4位是场景id高4位中的低高两位分别是xy
unsigned long long cw_static_pos_; // 进入副本前在普通场景的位置低4位是场景id高4位中的低高两位分别是xy
int war_team_id_; // 战队ID
int cross_honor_; // 跨服荣誉值
unsigned int upgrade_time_; //玩家等级升级的时间
unsigned int total_online_; //总的在线时长
unsigned int daily_online_; //单日在线时长
char quest[1000]; //任务的数据
char mis_for_php_[128]; //供后台查询的一些数据
tagActorDbData()
{
memset(this, 0, sizeof(tagActorDbData));
}
} ACTORDBDATA, *PACTORDBDATA;
*/

View File

@@ -0,0 +1,57 @@
#ifndef _CONFIG_DB_DATA_H_
#define _CONFIG_DB_DATA_H_
#define MAX_NAME_LEN 64
#define MAX_LEN_BUFF 64
#define MAX_LEN_DESC 1024
//礼包数据结构
typedef struct staticaward
{
int itemid; //礼包物品id
int needgrid; //需要格子数
char itemname[MAX_NAME_LEN];
char itemdesc[MAX_LEN_DESC];
//int itype; //物品类型
//int sell_type;
int icon; //图标id
//int color;
//int dura;
int dup; //物品可以重叠数量
//int colGroup;
//int dealType;
//int dealPrice;
int itime; //使用期限
unsigned int flag; //插数据库时插入一个已经标好位的
int grouptype; //分组类型没配置或0表示不按掉落组给全部奖励,1表示按掉落组配
int cond_cons_id; //开启条件物品id,没有填0
int cond_cons_count; //开启条件物品id数量,没有填0
int cond_money_type; //开启条件消耗钱类型没有填0
int cond_money_count; // 开启条件消耗钱数量没有填0
char cond_value[MAX_LEN_BUFF]; //用字符串表示条件, c1=v1&c2=v2&c3=v3采用这种形式
} Staticaward_t;
//礼包配置
typedef struct staticawardconfig
{
int giftitemid; // 礼包物品id
int rewardtype; //奖励类型 1 物品 2 金钱 ... 其余可自定义
int contenttype;// 奖励内容的类型 目前只用作金钱类型
int amount; // 奖励数量 物品数量 或者 金额
int itemid; //奖励物的id或物品id或技能id或
int bind; //是否绑定0表示非绑1表示绑定
int group; // 掉落组
int rate; //掉落概率
int noworldrate; //是否世界经验加成0加成1表示物无加成
int quality;
int strong;
}Staticawardconfig_t;
#endif

View File

@@ -0,0 +1,44 @@
#ifndef _CONSIGNMENT_H_
#define _CONSIGNMENT_H_
#include "common.h"
#include "item_data.h"
#include "common/datalist.h"
//禁止编译器对此结构进行字节对齐
#pragma pack (push, 1)
//
typedef struct tagConsingmentData
{
ItemSeries id_; // 唯一的id
ItemData* item_; //标准的物品结构
int sell_money_; // 出售的是金钱
int sell_money_type_; // 金钱类型,只能是非绑定的
UINT restTime_; //寄卖的剩余时间
UINT price_; //价钱
ActorId actorId_; //所有者的id
uint8_t moneyType_; //元宝或者银两
uint8_t bJob; //适用的职业0是通用见职业定义
uint8_t bType; //类型,
uint8_t bLevel; //物品使用所需的等级
uint8_t timeOut_; //是否过期0表示没过期否则表示过期
unsigned int handle_; //用于内存管理的handle
ACTORNAME actor_name_; //所有者名字
char account_name_[64]; // 账户名称
tagConsingmentData()
{
ZeroMemory(this, sizeof(*this));
}
static bool SortRule(tagConsingmentData* data1, tagConsingmentData* data2)
{
return (data1->moneyType_ == data2->moneyType_) ? (data1->price_ < data2->price_) : (data1->moneyType_ > data2->moneyType_);
}
}ConsingmentData;
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,151 @@
#ifndef _DB_FIGHT_H_
#define _DB_FIGHT_H_
#include "common.h"
#include "skill_data.h"
#include "common/datalist.h"
#define MAX_DB_SKILL 16
#define MAX_FIGHT_DATA 1000
#define FIGHT_PER_PAGE 15
#define MAX_FIGHT_LOG 50
#pragma pack(push, 1)
struct FightDBData
{
ActorId aid_;
ACTORNAME name_;
int serverid_;
int sex_;
int job_;
int fight_value_;
int gid_; // 所在帮派的ID
int weapon_; //武器外观
int wing_; //翅膀外观
int props_[P_MAX_CREATURE]; //一般生物属性集合
int hair_;
int sprite_; //精灵
int social_; //帮派职位
int guild_level_; //帮派排名
//以下全部添加到props下
//int level_;
//int icon_;
//int model_;
//int max_hp_;
//int max_mp_;
//int speed_;
//int out_attack_;
//int out_defence_;
//int in_attack_;
//int in_defence_;
//int all_attack_;
//int sub_def_;
//int baoji_;
//int shanbi_;
//int hit_rate_;
//int attack_append_;
//float hp_renew_;
//float mp_renew_;
//int attack_speed_;
//int in_attack_damage_add_;
//int out_attack_damage_add_;
//int lilian_; // 这期获得的历练(无用)
int skill_cnt_; // 技能数量
BaseSkillData skills_[MAX_DB_SKILL]; // 技能列表(角色技能)
int other_skill_cnt_; //其他系统技能数量
BaseSkillData other_skills_[MAX_DB_SKILL]; //其他系统的技能列表, 不包含被动技能(只加属性)
int nIndex; //当前排名
int prev_index; // 上次的排名,用于显示趋势,每天凌晨记录
int attack_type_; // 攻击类型
int init_data_; // 初始数据
FightDBData()
{
wing_ = 0;
hair_ = 0;
sprite_ = 0;
skill_cnt_ = 0;
other_skill_cnt_ = 0;
attack_type_ = 1;
weapon_ = 0;
social_ = 0;
guild_level_ = 0;
memset(props_, 0, sizeof(props_));
prev_index = 1000000;
}
// 获取排名趋势
int GetTrend()
{
if (nIndex > prev_index)
return 0;
else if (nIndex < prev_index)
return 2;
return 1;
}
};
// 对战玩家的数据
struct FightActorData
{
ActorId id_;
int rank_; // 对战后排名
int serverid_;
int sex_;
int job_;
int level_;
ACTORNAME name_;
};
// 竞技场对战记录
struct FightLogData
{
unsigned int time_; // 时间
FightActorData aid1_; // 挑战玩家
FightActorData aid2_; // 被挑战玩家
int result_; // 挑战结果
};
// 个人对战记录
struct FightLog
{
int date_;
int type_;
int result_;
int rank_; // 对战后排名
int enemyid_;
int encamp_;
int ensex_;
int enjob_;
int enlevel_;
ACTORNAME enname_;
};
// 宠物技能信息
struct FightPetSkill
{
int skillId_; // 技能id
int level_;
};
struct FightPetData
{
int title_; //
int mid_; // 怪物ID
int level_;
//int name_rgb_;
};
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,44 @@
#ifndef _FRIEND_DATA_H_
#define _FRIEND_DATA_H_
#include "common.h"
#pragma pack(push,1)
struct FriendInfo
{
ActorId actor_id_; //好友角色id
//int qq_vip_;
//unsigned int friendly_;//与该好友的友好度
//uint8_t icon_; //该好友的头像
uint8_t f_type_;
//int level_;
//uint8_t camp_;
//uint8_t job_;
//uint8_t sex_;
//uint32_t fight_; //战斗力
//uint32_t last_logout_time_;//离线时间
//uint32_t server_id_; //服务器ID
uint32_t add_friend_time_; //添加好友时间
uint32_t last_contact_time_; //最近联系时间
// 重载比较操作符在列表中会根据角色id作二分法查找
inline bool operator != (const FriendInfo& data) const
{
return actor_id_ != data.actor_id_;
}
inline bool operator > (const FriendInfo& data) const
{
return actor_id_ > data.actor_id_;
}
inline bool operator < (const FriendInfo& data) const
{
return actor_id_ < data.actor_id_;
}
};
#pragma pack (pop)
#endif

View File

@@ -0,0 +1,42 @@
#ifndef _GUILD_DB_H_
#define _GUILD_DB_H_
#include "common.h"
#define MAXMEMOCOUNT 1024
struct GuildMemberInfo
{
ActorId actorId_;
int total_contrib_;
int today_contrib_;
uint8_t job_; // 职业
uint8_t sex_;
uint8_t level_;//等级
uint8_t zs_level_;//转生等级
uint8_t pos_; //地位
double fight_; // 战力
int vip_; // vip等级
int monthcard_; // 月卡状态
uint8_t icon_; //头像ID
unsigned int lastLogoutTime_;
unsigned int recharge_;
ACTORNAME actor_name_;
uint64_t handle_;
GuildMemberInfo()
{
ZeroMemory(this, sizeof(*this));
}
int compare(GuildMemberInfo& node)
{
if (total_contrib_ > node.total_contrib_) return 1;
else if (total_contrib_ < node.total_contrib_) return -1;
else return 0;
}
};
#endif

View File

@@ -0,0 +1,90 @@
#ifndef _USER_ITEM_H_
#define _USER_ITEM_H_
#include "common.h"
// 暂时没用可以用varchar64来做这个
//#define ITEM_DATA_RESERVED_SIZE 64
#define EQUIP_ATTR_COUNT 8
#define ITEM_ATTR_TYPEVALUE 2
#define ITEM_ATTR_TYPE 0
#define ITEM_ATTR_VALUE 1
enum BagType
{
BagType_Item = 0,
BagType_Equip,
BagType_Depot,
};
#pragma pack (push, 1)
union ItemSeries
{
int64_t llId;
struct
{
unsigned int time_; //31-0位表示物品产生的日期和时间值为短日期类型单位是秒
uint16_t series_; //47-32位表示在一秒内的序列每产生一个物品则序列值+1一秒后序列值归零
uint16_t sid_; //55-48位表示服务器ID
} t;
public:
//inline operator int64_t () const { return llId; }
//inline bool operator == (const ItemSeries& series) const { return llId == series.llId; }
//inline bool operator != (const ItemSeries& series) const { return llId != series.llId; }
};
union ItemAttrData
{
// define:
struct EquipAttr
{
int attr[EQUIP_ATTR_COUNT][ITEM_ATTR_TYPEVALUE]; // 类型+value
};
// public:
EquipAttr equip_attr;
};
struct ItemData
{
int64_t uid; //物品唯一系列号 ItemSeries
int id;
int count;
ItemAttrData attr_data; // 大部分物品都是装备,且属性很少,不需要做优化
ItemAttrData ex_attr_data;
ItemData()
{
memset(this, 0, sizeof(ItemData));
}
public:
//修改useritem 注意需要修改以下3个函数 writeToPack, writeDbPack, writeCrcPack
//组装发送给客户端的包
void writeData(DataPacket& pack) {
pack.writeBuf(this, sizeof(ItemData));
}
void readData(DataPacketReader& pack) {
pack.readBuf(this, sizeof(ItemData));
}
static void copy(ItemData* dstItem, ItemData* srcItem)
{
if (!dstItem || !srcItem || dstItem == srcItem) return;
memcpy(dstItem, srcItem, sizeof(ItemData));
}
};
#pragma pack(pop)
//STATIC_ASSERT(sizeof(ItemData) < ITEM_DATA_RESERVED_SIZE);
typedef std::vector<ItemData*> ItemList ;
#endif

View File

@@ -0,0 +1,89 @@
#ifndef _MAIL_DATA_H_
#define _MAIL_DATA_H_
#include "common.h"
enum MailAwardType
{
MailAwardType_Currency,
MailAwardType_Item,
};
enum MailReadStatusType
{
MailReadStatusType_NotRead,
MailReadStatusType_HaveRead,
};
enum MailAwardStatusType
{
MailAwardStatusType_NoAward = -1, //无附件
MailAwardStatusType_CanAward = 0, //可领取
MailAwardStatusType_HaveAward = 1, //已领取
};
#pragma pack (push, 4)
union MailSeries
{
int64_t llId;
struct
{
unsigned int time_; //31-0位表示物品产生的日期和时间值为短日期类型单位是秒
uint16_t series_; //47-32位表示在一秒内的序列每产生一个物品则序列值+1一秒后序列值归零
uint16_t sid_; //55-48位表示服务器ID
} t;
public:
//inline operator int64_t () const { return llId; }
//inline bool operator == (const ItemSeries& series) const { return llId == series.llId; }
//inline bool operator != (const ItemSeries& series) const { return llId != series.llId; }
};
struct MailAwardData
{
int type; //附件类型
int id; //附件类型如果是物品的话就用来存物品id是货币的话就没用
int count; //数量
MailAwardData() :type(0), id(0), count(0) {}
};
struct MailAwardList
{
int awardCount; //附件数量
MailAwardData awardList[10]; //附件列表
};
struct MailData
{
static const int HEAD_SIZE = 128;
static const int CONTEXT_SIZE = 1024;
int uid; //邮件唯一系列号 MailSeries
int readStatus; //读取状态
int awardStatus; //领奖状态
int sendtime; //发送的时间
char head[128]; //邮件标题
char context[1024]; //邮件正文
MailAwardList award_data; // 大部分物品都是装备,且属性很少,不需要做优化
MailData()
{
memset(this, 0, sizeof(MailData));
}
public:
//修改useritem 注意需要修改以下3个函数 writeToPack, writeDbPack, writeCrcPack
//组装发送给客户端的包
void writeData(DataPacket& pack) {
pack.writeBuf(this, sizeof(MailData));
}
void readData(DataPacketReader& pack) {
pack.readBuf(this, sizeof(MailData));
}
};
#pragma pack(pop)
#endif

104
Gateway/common/db/msg.h Normal file
View File

@@ -0,0 +1,104 @@
#ifndef _MSG_H_
#define _MSG_H_
#define MAX_MSG_COUNT 1024 //这个跟数据库定义的长度相关,不能改
#define MAX_MAIL_COUNT 1024 //这个跟数据库定义的长度相关,不能改
#define MAX_MAIL_FILE_COUNT 3
#define MAX_MAIL_NOTIFY 180
//禁止编译器对此结构进行字节对齐
#pragma pack (push, 1)
//保存这个玩家的邮件消息
struct MailFile
{
uint8_t type_; // 0 NULL 1 物品 2 金钱
int sort_; // 物品ID或金钱种类1 元宝, 2 绑定元宝, 3 银两, 4 仙币)
int num_; // 数量
uint8_t bind_; // 是否绑定
int quality_; // 品质
MailFile()
{
ZeroMemory(this, sizeof(*this));
}
void reset()
{
ZeroMemory(this, sizeof(*this));
}
};
// struct MailData
// {
// int64_t id_;
// int actor_id_;
// uint8_t type_;
// uint8_t status_;
// int sender_id_;
// int sender_level_;
// uint32_t send_tick_;
// char send_name_[33];
// char context_[MAX_MAIL_COUNT];
// MailFile attachment_[MAX_MAIL_FILE_COUNT];
//
// MailData()
// {
// ZeroMemory(this, sizeof(*this));
// }
// void reset()
// {
// ZeroMemory(this, sizeof(*this));
// }
// };
struct GmQuestionData
{
int64_t id_;
int server_id_;
int actor_id_;
char name_[128];
int status_;
int hasread_;
char title_[128];
int type_;
char question_[1024];
char qq_[16];
unsigned int question_time_;
char answer_[1024];
unsigned int answer_time_;
GmQuestionData()
{
ZeroMemory(this, sizeof(*this));
}
void reset()
{
ZeroMemory(this, sizeof(*this));
}
};
struct FeeData
{
int id_;
char openid_[128];
int itemId_;
int num_;
int actor_id_;
char order_num_[128];
};
struct TxApiMsgData
{
int id_;
char openid_[128];
int type_;
char para1_[64];
char para2_[64];
char para3_[64];
char para4_[64];
char para5_[64];
};
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,19 @@
#ifndef _PET_H_
#define _PET_H_
#include "common/system_param_def.h"
#pragma pack(push,1)
struct PropData
{
int data_[PI_MAX];
};
#pragma pack (pop)
//lua里面也有限制
#define MAX_BLOOD 20
#endif

View File

@@ -0,0 +1,159 @@
#ifndef _DB_RANK_H_
#define _DB_RANK_H_
#include "container/static_array_list.h"
#include "common/datalist.h"
#include "common/gem_def.h"
#include "item_data.h"
#include "wing_data.h"
#include "achieve_data.h"
using namespace container;
#define MAX_USER_EQUIP 19
#define MAX_PET_SKILL 16
#define MAX_PET_BASE 8
#define MAX_FIGHT 40
#define NEED_REMEMBER_PROPERTY 20
#define MAX_PET_EQUIP 4
enum RankType
{
rtNone = 0,
rtFightVal = 1, // 战力排行
rtLevel = 2, // 等级排行
rtCharmWeek = 3,// 每周魅力排行
rtAchieve = 4, // 成就排行
rtPet = 5, // 宠物排行榜
rtMount = 6, // 坐骑排行
rtWing = 7, // 翅膀排行榜
rtSpirit = 8, // 精灵排行
rtCharm = 9, // 魅力排行(无用)
rtRoot = 10, // 灵根排行(无用)
rtMax,
};
#pragma pack(push, 1)
struct RankDbItem
{
ActorId actorId_;
int rankId_; // 排行榜的编号
int point_; // 排行的分数(如果是等级排行,这个就是等级,如果是魅力排行,这个就是魅力值)
int camp_; // 服务器id
int level_; // 等级
int job_; // 职业
int sex_; // 性别
int fightVal_; // 战斗力
int mount_id_;// 坐骑的阶值,用于客户端取得坐骑的名字
int spirit_id_; // 法宝的境界,用于客户端取得法宝的名字,注意,这些字段只有特定的排行榜才有用
int wing_; // 翅膀id
int pet_type_; // 宠物类型id
int pet_id_; // 宠物id
int qq_vip_; // qqvip等级
int weapon_; // 武器外观
int model_; // 衣服外观
int hair_; // 头发外观
int stone_effect_;//宝石特效
int stage_effect_;//阶级特效
int wing_model_;//翅膀外观
int last_rank_; // 上一次的排名
int like_; //点赞次数
int srvid_; // 服务器id
char actorName_[32]; //角色名
char guild_[32]; //仙宗名
char petName_[32]; //宠物名
static const int MAX_COUNT = 100;
RankDbItem() : actorId_(0), rankId_(0), point_(0), camp_(0), level_(1), job_(0), sex_(0), fightVal_(0), mount_id_(0),
spirit_id_(0), wing_(0), pet_type_(0), pet_id_(0), qq_vip_(0), weapon_(0), model_(0), hair_(0), stone_effect_(0), stage_effect_(0), wing_model_(0), last_rank_(0), like_(0), srvid_(0)
{
actorName_[0] = 0;
guild_[0] = 0;
petName_[0] = 0;
}
};
#pragma pack(pop)
#pragma pack(push, 1)
struct PetRankDbItem
{
ActorId actorId_;
int jingjie_; //宠物境界
int nature_; //宠物性格
short pet_type_; //宠物外观idx
short skill_count_; //技能个数
int skill_list_[MAX_PET_SKILL]; //一个int包含技能id和等级 (低16 技能id 高16 等级)
StaticDataList<ItemData, MAX_PET_EQUIP> items_;//宠物装备
static const int MAX_COUNT = 100;
PetRankDbItem() : actorId_(0), jingjie_(0), nature_(0), pet_type_(0), skill_count_(0)
{
memset(skill_list_, 0, sizeof(skill_list_));
}
};
#pragma pack(pop)
typedef StaticArrayList<RankDbItem, RankDbItem::MAX_COUNT> RankList;
typedef StaticArrayList<PetRankDbItem, PetRankDbItem::MAX_COUNT> PetRankList;
typedef StaticHashTable<int, RankDbItem::MAX_COUNT> LastRankList;
typedef StaticDataList<RankList, rtMax> AllRankList;
typedef StaticDataList<LastRankList, rtMax> AllLastRankList;
#pragma pack(push, 1)
struct RankData
{
int property_[NEED_REMEMBER_PROPERTY]; //属性值
int fight_list_[MAX_FIGHT]; //战斗力值
RankData()
{
memset(property_, (int)0, sizeof(property_));
memset(fight_list_, (int)-1, sizeof(fight_list_));
}
};
#pragma pack(pop)
struct ActorRankData
{
ActorId actorId_; //角色id
int dragon_; //神龙信息(无用)
int hasMount_; //是否有坐骑数据
//MountDataDb mount_data_;//坐骑数据
StaticDataList<ItemData, MAX_USER_EQUIP> items_;//玩家装备
int hasWing_; //是否有翅膀数据
WingRankDbData wing_data_;//翅膀数据
int hasSpirit_; //是否有精灵数据
SpiritRankData spirit_data_; //精灵数据
AchieveRankData achieve_data_; //成就数据
RankData rank_data_; //排行榜杂七杂八数据
uint8_t rankNum_[rtMax]; // 在每个榜的排名如果没排上就是0
ActorRankData() : actorId_(0), dragon_(0), hasMount_(0), hasWing_(0), hasSpirit_(0)
{
memset(rankNum_, 0, sizeof(rankNum_));
}
};
struct ActorRankDataEx
{
ActorRankData base_;
char guild_[32]; // 冗余,方便查找
int mount_id_; // 坐骑的阶值,用于客户端取得坐骑的名字
int spirit_id_; // 法宝的境界,用于客户端取得法宝的名字,注意,这些字段只有特定的排行榜才有用
int root_; // 灵根的等级数据
int wing_; // 翅膀
ActorRankDataEx() : mount_id_(0), spirit_id_(0), root_(0), wing_(0)
{
guild_[0] = 0;
}
};
#endif

View File

@@ -0,0 +1,170 @@
#ifndef _DB_ROLE_DATA_H_
#define _DB_ROLE_DATA_H_
#include "common.h"
#include "common/datalist.h"
#include "common/property_set.h"
#define MAX_FUWEN 8
#define MAX_WING_PILL 2 //翅膀提升丹种类
#pragma pack(push,1)
using namespace SrvDef;
//tolua_begin
struct SkillsData
{
int skill_level[5];
};
struct YuanShenData
{
bool slot_filled[6];
};
enum EquipSlotType
{
EquipSlotType_Weapon = 0,//武器
EquipSlotType_Helmet,//1.头盔
EquipSlotType_Coat,//2.衣服
EquipSlotType_Necklace,//3.项链
EquipSlotType_Wrist,//4.护腕
EquipSlotType_Belt,//5.腰带
EquipSlotType_Ring,//6.戒指
EquipSlotType_Shoes,//7.鞋子
EquipSlotType_Dzi, //8.官印
EquipSlotType_Hats, //9.斗笠
EquipSlotType_Mark, //10.面甲
EquipSlotType_Cloak, //11.披风
EquipSlotType_Shield, //12.盾牌
EquipSlotType_Max,
};
enum WingSlotType
{
WingSlotType_Hub = 0,
WingSlotType_Stone,
WingSlotType_Feathers,
WingSlotType_Colorplume,
WingSlotType_Max,
};
struct EquipSlotData
{
int strength_lv; //强化等级
int fuling_lv; //附灵等级
int gem_lv; //宝石等级
ItemData equip_data;
int zhuling_lv; //注灵等级
int soul_lv; //魔魂等级(1-8部位表示至尊等级9-12表示魔魂等级)
int bless_lv; //祝福等级(开光)(暂没用到)
int fuling_exp; //附灵经验
};
struct EquipsData
{
EquipSlotData slot_data[EquipSlotType_Max];
};
struct ExRingsData
{
int ring_level[4];
};
struct WingsData
{
int level;
//int star_lv;
int exp;
int openStatus;
unsigned int ctime;//清空时间
short pill[MAX_WING_PILL];
};
struct WingsEquip
{
EquipSlotData wing_slot[WingSlotType_Max];
};
//经脉系统数据
struct JingMaiData
{
int level;
int stage;
};
struct SkillsBreakData
{
int skill_break_level[5];
};
//龙魂数据
struct LoogsoulData
{
int stage;
int level;
int exp;
char act;
};
struct ShieldData
{
int stage;
int level;
int exp;
char act;
};
struct XueyuData
{
int stage;
int level;
int exp;
char act;
};
struct FuWenData
{
ItemData fuwen_slot[MAX_FUWEN];
};
#define HEIRLOOM_TYPE_MAX 8 //传世装备最大部位数量
//修改RoleData的话要通知客户端修改同步RoleData的协议
struct RoleData
{
int id;
int job;
int sex;
double power;
SkillsData skills;
SkillsBreakData skillbreaks;
int yuanshen_level;
YuanShenData yuanshen_data;
EquipsData equips_data;
ExRingsData ex_rings;
WingsData wings;
//WingsEquip wingequips_data;
JingMaiData jingmai_data;
LoogsoulData loogsoul_data;
//ShieldData shield_data;
//XueyuData xueyu_data;
FuWenData fuwen_data;
int heirloom[HEIRLOOM_TYPE_MAX];
int weapon_soul_id;//当前使用的兵魂ID
};
struct RoleDatas
{
int role_count;
RoleData roles[3];
RoleDatas() { memset(this, 0, sizeof(RoleDatas)); }
};
//tolua_end
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,36 @@
#ifndef _SKILL_DB_DATA_H_
#define _SKILL_DB_DATA_H_
#include "common.h"
/****************************************************************************************
* 技能DB相关的一些结构体的定义
****************************************************************************************/
//玩家的一个技能需要存盘的数据
#pragma pack(push, 1)
struct BaseSkillData
{
uint16_t sid_; //技能的ID
unsigned char level_; //技能的等级,如果没有学习就是0
unsigned int cool_sec_; //冷却时间(单位秒)
unsigned int exp_; //技能的经验
};
struct PetSkillDb
{
int skillid_;
int level_;
int exp_;
unsigned int cd_;
int r1_;
int r2_;
int r3_;
PetSkillDb()
{
memset(this, 0, sizeof(*this));
}
};
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,33 @@
#ifndef _STORE_DATA_H_
#define _STORE_DATA_H_
#include "common.h"
#include "item_data.h"
struct StoreItemData
{
int id; //商品id
int currency_type; //购买的货币类型
int currency; //购买需要的货币数量
int discount; //折扣类型1是8折2是5折
ItemData itemData; //道具数据
StoreItemData()
{
memset(this, 0, sizeof(StoreItemData));
}
public:
//修改useritem 注意需要修改以下3个函数 writeToPack, writeDbPack, writeCrcPack
//组装发送给客户端的包
void writeData(DataPacket& pack) {
pack.writeBuf(this, sizeof(StoreItemData));
}
void readData(DataPacketReader& pack) {
pack.readBuf(this, sizeof(StoreItemData));
}
};
#endif

View File

@@ -0,0 +1,15 @@
#ifndef _TABLE_DEFS_H_
#define _TABLE_DEFS_H_
// 数据库字段类型
enum DB_FILED_TYPE {
ftInt = 0,
ftDouble,
ftString,
ftInt64,
ftBlob,
ftCount,
};
#endif

View File

@@ -0,0 +1,32 @@
#ifndef _WING_H_
#define _WING_H_
#include "common.h"
#include "skill_data.h"
#include "common/datalist.h"
#define MAX_WING_SKILL 8 //对应wingsystem的MAX_SKILL
#define MAX_WING_EQUIP 4
#pragma pack(push, 1)
struct WingSkill : public BaseSkillData
{
int64_t guid_;
};
struct WingRankData
{
int skill_grid_; //技能空格
int skill_cnt_; //技能个数
BaseSkillData skill_list_[MAX_WING_SKILL];
};
struct WingRankDbData
{
WingRankData data_;
StaticDataList<ItemData, MAX_WING_EQUIP> equip_;
};
#pragma pack(pop)
#endif

4926
Gateway/common/dbghelp.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
EXPORTS
;MBCSDef
CreateMBCSFilter
FreeMBCSFilter
MemoryUsageOfMBCSFilter
LoadMBCSFilterWords
SaveMBCSFilterWords
MatchMBCSFilterWord
AddMBCSFilterStrToTable
;UCSDef
CreateUCSFilter
FreeUCSFilter
MemoryUsageOfUCSFilter
LoadUCSFilterWords
SaveUCSFilterWords
MatchUCSFilterWord
AddUCSFilterStrToTable

View File

@@ -0,0 +1,8 @@
#ifndef _FASTFTMAIN_H_
#define _FASTFTMAIN_H_
#include "MBCSDef.h"
//#include "UCSDef.h"
#endif

View File

@@ -0,0 +1,69 @@
#--------------------------makefile description-----------------------------#
#use for gcc/g++ compiler to complate/link
#edited: miros
#edit time: Sep 8, 2007
#------------------------compiler and compiler fags-------------------------#
COMPILER=gcc
#COMPLATEFLAGS=-g -D LINUX -D GUN_GCC -I ./../../common/
COMPLATEFLAGS=-g -D FREEBSD -D GUN_GCC -I ./../../common/
LINKER=ar
LINKFLAGS=cvr
DEBUGER=gdb
#--------------------------project settings---------------------------------#
PROJECTNAME=../libs/bsd/dbg/fastFT.a
INCLUDES=./MBCSFilter.c\
./UCSFilter.c
#LIBS=
LIBS=
OBJECTS=./MBCSFilter.o ./UCSFilter.o
#EXTEDOBJECTS=
EXTEDOBJECTS=
#------------------------------make actions---------------------------------#
#use build to be default command
build: complate link
complate:
@echo "compiler: ${COMPILER}"
@echo "begin complate source files:"
@echo "${INCLUDES}"
@$(COMPILER) $(COMPLATEFLAGS) $(INCLUDES) -c $^
@echo "complate succeeded"
recomplate: cleanobjs complate
link:
@echo "linker: ${LINKER}"
@echo "begin link object files:"
@echo "${OBJECTS}"
@$(LINKER) $(LINKFLAGS) $(PROJECTNAME) $(OBJECTS)
@echo "Done!"
cleanobjs:
@-rm $(OBJECTS)
cleanapps:
@-rm $(PROJECTNAME)
cleanall: cleanobjs cleanapps
rebuild: cleanall build
build-clear: build cleanobjs
all: rebuild cleanobjs
#----------------------------exports labdles--------------------------------#
.PHONY: all build rebuild complate recomplate link cleanobjs cleanapps cleanall build-clear

View File

@@ -0,0 +1,74 @@
#ifndef _MBCSDEF_H_
#define _MBCSDEF_H_
#define MBCSARRAY_SIZE 255
#define NEW_FILTER
#pragma pack(push, 1)
typedef struct tagFT_mbcs_char
{
char wordEnd; //到此字符是否构成一个完整的屏蔽词
#ifdef NEW_FILTER
unsigned char idx[MBCSARRAY_SIZE];
unsigned char count;
tagFT_mbcs_char** mem;
#else
struct tagFT_mbcs_char* next[MBCSARRAY_SIZE]; //当前字符的后续字符表,访问索引为字符值-1
#endif
#ifdef NEW_FILTER
tagFT_mbcs_char* getNext(int index)
{
if (!mem) return NULL;
unsigned char ridx = idx[index];
if (ridx == 0) return NULL;
return mem[ridx - 1];
}
void addNext(int index, tagFT_mbcs_char* next);
#else
tagFT_mbcs_char* getNext(int index)
{
return next[index];
}
void addNext(int index, tagFT_mbcs_char* next)
{
next[index] = next;
}
#endif
}FT_MBCS_CHAR, *PFT_MBCS_CHAR;
#pragma pack(pop)
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef STDCALL
#if (defined(WIN32) || defined(WINDOWS))
#define STDCALL __stdcall
#else
#define STDCALL
#endif
#endif
/*
创建一个MBCS屏蔽词表
*/
PFT_MBCS_CHAR CreateMBCSFilter(void*);
/*
销毁一个MBCS屏蔽词表释放表使用的所有内存
*/
void STDCALL FreeMBCSFilter(PFT_MBCS_CHAR filter);
int STDCALL LoadMBCSFilterWords(PFT_MBCS_CHAR filter, const char *fn);
char* STDCALL MatchMBCSFilterWord(const PFT_MBCS_CHAR filter, const char *input, int *matchLen);
//把一个字符串加入到屏蔽词表中
int STDCALL AddMBCSFilterStrToTable(PFT_MBCS_CHAR filter,const char* str);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,174 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "mbcs_def.h"
#include "memory/base_allocator.hpp"
#define toupper(c) (((c) >= 'a' && (c) <= 'z') ? (c) ^ 0x20 : (c))
BaseAllocator mbcsFilter("mbcsFilter");
#ifdef NEW_FILTER
void tagFT_mbcs_char::addNext(int index, tagFT_mbcs_char* next)
{
unsigned char ridx = idx[index];
assert(ridx == 0);
mem = (tagFT_mbcs_char**)mbcsFilter.ReAllocBuffer(mem, (count + 1) * sizeof(tagFT_mbcs_char*));
mem[count] = next;
count++;
idx[index] = count;
}
#endif
//把一个字符串加入到屏蔽词表中
int STDCALL AddMBCSFilterStrToTable(PFT_MBCS_CHAR filter, const char* str)
{
int len = (int)strlen(str);
PFT_MBCS_CHAR prev = filter;
if (!filter)
return 0;
for (int i = 0; i < len; i++)
{
unsigned char index = str[i];
index = toupper(index) - 1;
PFT_MBCS_CHAR next = prev->getNext(index);
if (!next)
{
next = CreateMBCSFilter(0);
prev->addNext(index, next);
}
if (i == (len - 1))
next->wordEnd = 1;
prev = next;
}
return 1;
}
//-----------------------------------------------------------------------
PFT_MBCS_CHAR CreateMBCSFilter(void*)
{
PFT_MBCS_CHAR pMBCSChar =
(PFT_MBCS_CHAR)mbcsFilter.AllocBuffer(sizeof(FT_MBCS_CHAR));
memset(pMBCSChar, 0, sizeof(FT_MBCS_CHAR));
return pMBCSChar;
}
void STDCALL FreeMBCSFilter(PFT_MBCS_CHAR filter)
{
if (!filter) return;
#ifdef NEW_FILTER
if (filter->count > 0)
{
for (int i = 0; i < filter->count; i++)
{
PFT_MBCS_CHAR next = filter->mem[i];
if (next) FreeMBCSFilter(next);
}
}
mbcsFilter.FreeBuffer(filter->mem);
#else
for (int i = 0; i < MBCSARRAY_SIZE; i++)
{
PFT_MBCS_CHAR next = filter->next[i];
if (next) FreeMBCSFilter(next);
}
#endif
mbcsFilter.FreeBuffer(filter);
filter = NULL;
}
int STDCALL LoadMBCSFilterWords(PFT_MBCS_CHAR filter, const char* fn)
{
int nStrCount = 0;
char szText[256] = {0};
char* pStr = 0;
FILE* fl = fopen(fn, "r");
//检查并跳过UTF-8文件BOM
fread(szText, 3, 1, fl);
if ((*(int*)szText & 0x00FFFFFF) != 0xBFBBEF)
fseek(fl, 0, 0);
while ((pStr = fgets(szText, 256, fl)))
{
size_t nLen = strlen(szText);
while (nLen > 0 && ((unsigned int)szText[nLen - 1] <= 0x20))
{
szText[nLen - 1] = 0;
nLen--;
}
if (nLen > 0 && AddMBCSFilterStrToTable(filter, szText))
++nStrCount;
}
fclose(fl);
return nStrCount;
}
char* STDCALL MatchMBCSFilterWord(const PFT_MBCS_CHAR filter, const char* input, int* matchLen)
{
char* matchStart = NULL; //被匹配的输入字符串的起始字符指针
char* matchEnd = NULL; //被匹配的字符串的结束字符之后的一个字符的指针,此值减去lpMatchStart即为被匹配字符串的长度
unsigned char ch;
while ((ch = *input))
{
ch = toupper(ch);
PFT_MBCS_CHAR curFTChar = filter->getNext(ch - 1);
if (curFTChar)
{
char* test = matchStart = (char*)input;
do
{
test++;
//到该字符是否处构成了完整的匹配词
if (curFTChar->wordEnd)
matchEnd = test;
//继续向后匹配
ch = *test;
if (!ch) break;
ch = toupper(ch);
curFTChar = curFTChar->getNext(ch - 1);
}
while (curFTChar && *test);
//出现了完整的匹配词则终止
if (matchEnd)
break;
}
//对于MBCS进入下一个字符应当跳过2个字符
//if ( (unsigned char)(*pInput) >= 0x80 )
// pInput += 2;
//else pInput += 1;
input++;
}
char* result = (matchEnd ? matchStart : NULL);
if (matchLen)
*matchLen = (int)(size_t)(result ? (matchEnd - matchStart) : 0);
return result;
}

View File

@@ -0,0 +1,177 @@
#include <stdio.h>
#include "os_def.h"
#include "_ast.h"
#include <zlib.h>
#include "stream.h"
#include "zstream.h"
#include "game_map.h"
#include "memory/base_allocator.hpp"
#ifndef _MSC_VER
#include <arpa/inet.h>
#endif
using namespace stream;
using namespace zstream;
BaseAllocator GameMap::mapAlloc_("mapAlloc");
GameMap::GameMap()
{
width_ = 0;
height_ = 0;
moveable_index_ = NULL;
moveable_ount_ = 0;
}
GameMap::~GameMap()
{
if (moveable_index_)
mapAlloc_.FreeBuffer(moveable_index_);
}
bool GameMap::LoadFromStream(BaseStream& stream, bool newver)
{
MAPFILE_HEADER hdr;
MAPGrid* map_grid, *grid_ptr;
MAPFILE_HEADER_NEW hdr_n;
MAPGrid_NEW* map_grid_n, *grid_ptr_n;
if (!newver)
{
//读取并检查文件头
if (stream.read(&hdr, sizeof(hdr)) != sizeof(hdr))
return false;
if (hdr.version_ != MapFileVersion_Current)
return false;
}
//将压缩过的坐标数据段读取到内存流
MemoryStream ms(NULL);
if (newver)
ms.copyFrom(stream, stream.getSize());
else
ms.copyFrom(stream, hdr.data_size_);
ms.setPosition(0);
//从内存流中创建解压流,以便解压坐标数据
ZDecompressionStream deStream(ms, NULL);
if (newver)
{
//读取并检查文件头
if (deStream.read(&hdr_n, sizeof(hdr_n)) != sizeof(hdr_n))
return false;
// 地图打包文件,按照大头的字节序打包了
hdr_n.width_ = ntohl(hdr_n.width_);
hdr_n.height_ = ntohl(hdr_n.height_);
}
int max = 0;
if (newver)
{
size_t grid_count = sizeof(MAPGrid_NEW) * hdr_n.width_ * hdr_n.height_;
grid_ptr_n = map_grid_n = (MAPGrid_NEW*)mapAlloc_.AllocBuffer(grid_count);
if (grid_count != (const size_t)deStream.read(map_grid_n, (const int)grid_count))
return false;
max = hdr_n.width_ * hdr_n.height_;
}
else
{
size_t grid_count = sizeof(MAPGrid) * hdr.width_ * hdr.height_;
grid_ptr = map_grid = (MAPGrid*)mapAlloc_.AllocBuffer(grid_count);
if (grid_count != (const size_t)deStream.read(map_grid, (const int)grid_count))
return false;
max = hdr.width_ * hdr.height_;
}
moveable_ount_ = 0;
int* index_ptr = moveable_index_ = (int*)mapAlloc_.ReAllocBuffer(moveable_index_, max * sizeof(*index_ptr));
memset(index_ptr, -1, max * sizeof(*index_ptr)); // 如果是memset其他值会有问题
//保存地图宽度以及高度数据
if (newver)
{
// 这个索引值跟旧版本的不一样
for (int i = 0; i < max; ++i)
{
if (grid_ptr_n->flag_ != gfBlock /*&& grid_ptr_n->flag_ != gfNofly*/)//不是明确的不可走点,都认为可走就行了
{
int x = i / hdr_n.height_;
int y = i % hdr_n.height_;
(*(index_ptr + (y * hdr_n.width_ + x))) = moveable_ount_;
moveable_ount_++;
}
//index_ptr++;
grid_ptr_n++;
}
width_ = hdr_n.width_;
height_ = hdr_n.height_;
mapAlloc_.FreeBuffer(map_grid_n);
}
else
{
for (int i = 0; i < max; ++i)
{
if ((grid_ptr->flag_ & MAPFLAG_MOVEABLE) != 0)
{
(*index_ptr) = moveable_ount_;
moveable_ount_++;
}
index_ptr++;
grid_ptr++;
}
width_ = hdr.width_;
height_ = hdr.height_;
mapAlloc_.FreeBuffer(map_grid);
}
return true;
}
bool GameMap::LoadFromFile(const char* fn, bool newver)
{
FileStream fs(fn, FileStream::faRead || FileStream::faShareRead, NULL);
return LoadFromStream(fs, newver);
}
void GameMap::initDefault(unsigned int w, unsigned int h)
{
// 特定地方才会用到这个函数,全部网格设置成可以走动
//生成抽象灰度地图
int max = w * h;
moveable_ount_ = 0;
int* index_ptr = moveable_index_ = (int*)mapAlloc_.ReAllocBuffer(moveable_index_, max * sizeof(*index_ptr));
for (int i = 0; i < max; ++i)
{
(*index_ptr) = moveable_ount_;
moveable_ount_++;
index_ptr++;
}
//保存地图宽度以及高度数据
width_ = w;
height_ = h;
}

View File

@@ -0,0 +1,142 @@
#ifndef _GAME_MAP_H_
#define _GAME_MAP_H_
/*************************************************************
* 地图数据读取后将不保存用于显示的图片编号等数据,而仅仅
* 保存用于进行逻辑处理的点阵数据——使用一个字节表示一个坐标。
* 当坐标数据的值为1的时候表示该坐标可以移动否则表示该
* 坐标不可移动。
*
************************************************************/
//当前地图版本号
const unsigned int MapFileVersion_Current = 0x0102;
//不可移动标记
const unsigned int MAPFLAG_MOVEABLE = 0x8000;
/*
* 地图文件头结构
*/
#pragma pack(push, 1)
struct MAPFILE_HEADER_NEW
{
char hdr_[5]; //"map"
int ver_;
unsigned char grid_size_; // 常量64像素
int pxi_width_; // 地图的像素大小
int pix_height_;
int width_; //地图宽度
int height_; //地图高度
};
struct MAPFILE_HEADER
{
unsigned int version_; //文件版本0x0101
int width_; //地图宽度
int height_; //地图高度
int bg_img_; //地图背景图片编号
unsigned int data_size_; //地图坐标数据段字节长度
unsigned char reseve_[32];
};
// 地图网格的结构
struct MAPGrid
{
unsigned short bg_img_; // 背景图片编号
unsigned short ft_img_; // 前景图片编号
unsigned short flag_; // 地图坐标标志位
unsigned char obj_root_; // 素材分类索引
unsigned char reseve_; // 图片类型
unsigned short effect_id_; // 地图的特效id
unsigned short width_; // 特效的宽度
unsigned short height_; // 特效的高度
} ;
enum GripFlag
{
gfBlock = 0, //阻挡
gfCanMove = 1, //行走区
gfThrough = 2, //透明区
gfNofly = 3, //阻挡且不能飞跃
};
struct MAPGrid_NEW
{
unsigned char flag_; // 0=阻档1=行走区,2=透明区,3=阻挡且不能飞跃
};
#pragma pack(pop)
class GameMap
{
private:
static BaseAllocator mapAlloc_;
protected:
unsigned int width_; // 地图宽度
unsigned int height_; // 地图高度
int* moveable_index_; // 每坐标对应的可移动索引,主要是用于省内存的优化,暂时没使用到
int moveable_ount_; // 移动坐标数量
public:
GameMap();
virtual ~GameMap();
/* 从流中加载地图数据 */
bool LoadFromStream(stream::BaseStream& stream, bool newver);
/* 从文件中加载地图数据 */
bool LoadFromFile(const char* fn, bool newver);
/* 生成一张全部可以移动的地图 */
void initDefault(unsigned int w, unsigned int h);
/* 获取地图宽度 */
inline int getWidth()
{
return width_;
}
/* 获取地图高度 */
inline int getHeight()
{
return height_;
}
/* 获取可移动坐标数量 */
inline int getMoveableCount()
{
return moveable_ount_;
}
/* 获取地图中所有单元数目 */
inline int getUnitCount() const
{
return width_ * height_;
}
inline int getPosIndex(unsigned int x, unsigned int y)
{
if (x >= width_ || y >= height_)
return -1;
return y * width_ + x;
}
/* 判断地图中x, y坐标位置是否可以移动返回true表示坐标可以移动 */
inline bool canMove(unsigned int x, unsigned int y)
{
if (x >= width_ || y >= height_)
return false;
return moveable_index_[y * width_ + x] != -1;
}
int getMapPosValue(unsigned int x, unsigned int y)
{
if (x >= width_ || y >= height_)
return -1;
return moveable_index_[y * width_ + x] != -1 ? 0 : -1;
}
};
#endif

View File

@@ -0,0 +1,766 @@
/*
A* Algorithm Implementation using STL is
Copyright (C)2001-2005 Justin Heyes-Jones
Permission is given by the author to freely redistribute and
include this code in any program as long as this credit is
given where due.
COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE
IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED
CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL
DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE
OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
THIS DISCLAIMER.
Use at your own risk!
*/
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <_ast.h>
#include <stream.h>
//#include <iostream>
//#include <conio.h>
#include <assert.h>
#include "memory/objpool.hpp"
// stl includes
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
// fast fixed size memory allocator, used for fast node memory management
//#include "fsa.h"
// Fixed size memory allocator can be disabled to compare performance
// Uses std new and delete instead if you turn it off
#define USE_FSA_MEMORY 1
// disable warning that debugging information has lines that are truncated
// occurs in stl headers
#pragma warning( disable : 4786 )
// The AStar search class. UserState is the users state space type
template <class UserState> class AStarSearch
{
public: // data
enum
{
SEARCH_STATE_NOT_INITIALISED,
SEARCH_STATE_SEARCHING,
SEARCH_STATE_SUCCEEDED,
SEARCH_STATE_FAILED,
SEARCH_STATE_OUT_OF_MEMORY,
SEARCH_STATE_INVALID
};
// A node represents a possible state in the search
// The user provided state type is included inside this type
public:
class Node
{
public:
Node *parent; // used during the search to record the parent of successor nodes
Node *child; // used after the search for the application to view the search in reverse
int g; // cost of this node + it's predecessors
int h; // heuristic estimate of distance to goal
int f; // sum of cumulative cost of predecessors and self and heuristic
Node() :
parent( 0 ),
child( 0 ),
g(0 ),
h( 0),
f( 0 )
{
}
UserState m_UserState;
};
// For sorting the heap the STL needs compare function that lets us compare
// the f value of two nodes
class HeapCompare_f
{
public:
bool operator() ( const Node *x, const Node *y ) const
{
return x->f > y->f;
}
};
public: // methods
// constructor just initialises private data
AStarSearch( int MaxNodes = 1000 ) :
m_AllocateNodeCount(0),
#if USE_FSA_MEMORY
m_FixedSizeAllocator( "Astar" ),
#endif
m_State( SEARCH_STATE_NOT_INITIALISED ),
m_CurrentSolutionNode( NULL ),
m_CancelRequest( false )
{
}
// call at any time to cancel the search and free up all the memory
void CancelSearch()
{
m_CancelRequest = true;
}
// Set Start and goal states
void SetStartAndGoalStates( UserState &Start, UserState &Goal )
{
m_CancelRequest = false;
m_Start = AllocateNode();
m_Goal = AllocateNode();
assert((m_Start != NULL && m_Goal != NULL));
m_Start->m_UserState = Start;
m_Goal->m_UserState = Goal;
m_State = SEARCH_STATE_SEARCHING;
// Initialise the AStar specific parts of the Start Node
// The user only needs fill out the state information
m_Start->g = 0;
m_Start->h = m_Start->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState );
m_Start->f = m_Start->g + m_Start->h;
m_Start->parent = 0;
// Push the start node on the Open list
m_OpenList.push_back( m_Start ); // heap now unsorted
// Sort back element into heap
push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
// Initialise counter for search steps
m_Steps = 0;
}
// Advances search one step
unsigned int SearchStep()
{
// Firstly break if the user has not initialised the search
assert( (m_State > SEARCH_STATE_NOT_INITIALISED) &&
(m_State < SEARCH_STATE_INVALID) );
// Next I want it to be safe to do a searchstep once the search has succeeded...
if ( (m_State == SEARCH_STATE_SUCCEEDED) ||
(m_State == SEARCH_STATE_FAILED)
)
{
return m_State;
}
// Failure is defined as emptying the open list as there is nothing left to
// search...
// New: Allow user abort
if ( m_OpenList.empty() || m_CancelRequest )
{
FreeAllNodes();
m_State = SEARCH_STATE_FAILED;
return m_State;
}
// Incremement step count
m_Steps ++;
// Pop the best node (the one with the lowest f)
Node *n = m_OpenList.front(); // get pointer to the node
pop_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
m_OpenList.pop_back();
// Check for the goal, once we pop that we're done
if ( n->m_UserState.IsGoal( m_Goal->m_UserState ) )
{
// The user is going to use the Goal Node he passed in
// so copy the parent pointer of n
m_Goal->parent = n->parent;
// A special case is that the goal was passed in as the start state
// so handle that here
if ( false == n->m_UserState.IsSameState( m_Start->m_UserState ) )
{
FreeNode( n );
// set the child pointers in each node (except Goal which has no child)
Node *nodeChild = m_Goal;
Node *nodeParent = m_Goal->parent;
do
{
nodeParent->child = nodeChild;
nodeChild = nodeParent;
nodeParent = nodeParent->parent;
}
while( nodeChild != m_Start ); // Start is always the first node by definition
}
// delete nodes that aren't needed for the solution
FreeUnusedNodes();
m_State = SEARCH_STATE_SUCCEEDED;
return m_State;
}
else // not goal
{
// We now need to generate the successors of this node
// The user helps us to do this, and we keep the new nodes in
// m_Successors ...
m_Successors.clear(); // empty vector of successor nodes to n
// User provides this functions and uses AddSuccessor to add each successor of
// node 'n' to m_Successors
bool ret = n->m_UserState.GetSuccessors( this, n->parent ? &n->parent->m_UserState : NULL );
if ( !ret )
{
typename vector< Node * >::iterator successor;
// free the nodes that may previously have been added
for ( successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ )
{
FreeNode( (*successor) );
}
m_Successors.clear(); // empty vector of successor nodes to n
// free up everything else we allocated
FreeAllNodes();
m_State = SEARCH_STATE_OUT_OF_MEMORY;
return m_State;
}
// Now handle each successor to the current node ...
for ( typename vector< Node * >::iterator successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ )
{
// The g value for this successor ...
int newg = n->g + n->m_UserState.GetCost( (*successor)->m_UserState );
// Now we need to find whether the node is on the open or closed lists
// If it is but the node that is already on them is better (lower g)
// then we can forget about this successor
// First linear search of open list to find node
typename vector< Node * >::iterator openlist_result;
for ( openlist_result = m_OpenList.begin(); openlist_result != m_OpenList.end(); openlist_result ++ )
{
if ( (*openlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) )
{
break;
}
}
if ( openlist_result != m_OpenList.end() )
{
// we found this state on open
if ( (*openlist_result)->g <= newg )
{
FreeNode( (*successor) );
// the one on Open is cheaper than this one
continue;
}
}
typename vector< Node * >::iterator closedlist_result;
for ( closedlist_result = m_ClosedList.begin(); closedlist_result != m_ClosedList.end(); closedlist_result ++ )
{
if ( (*closedlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) )
{
break;
}
}
if ( closedlist_result != m_ClosedList.end() )
{
// we found this state on closed
if ( (*closedlist_result)->g <= newg )
{
// the one on Closed is cheaper than this one
FreeNode( (*successor) );
continue;
}
}
// This node is the best node so far with this particular state
// so lets keep it and set up its AStar specific data ...
(*successor)->parent = n;
(*successor)->g = newg;
(*successor)->h = (*successor)->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState );
(*successor)->f = (*successor)->g + (*successor)->h;
// Remove successor from closed if it was on it
if ( closedlist_result != m_ClosedList.end() )
{
// remove it from Closed
FreeNode( (*closedlist_result) );
m_ClosedList.erase( closedlist_result );
// Fix thanks to ...
// Greg Douglas <gregdouglasmail@gmail.com>
// who noticed that this code path was incorrect
// Here we have found a new state which is already CLOSED
// anus
}
// Update old version of this node
if ( openlist_result != m_OpenList.end() )
{
FreeNode( (*openlist_result) );
m_OpenList.erase( openlist_result );
// re-make the heap
// make_heap rather than sort_heap is an essential bug fix
// thanks to Mike Ryynanen for pointing this out and then explaining
// it in detail. sort_heap called on an invalid heap does not work
make_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
}
// heap now unsorted
m_OpenList.push_back( (*successor) );
// sort back element into heap
push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
}
// push n onto Closed, as we have expanded it now
m_ClosedList.push_back( n );
} // end else (not goal so expand)
return m_State; // Succeeded bool is false at this point.
}
// User calls this to add a successor to a list of successors
// when expanding the search frontier
bool AddSuccessor( UserState &State )
{
Node *node = AllocateNode();
if ( node )
{
node->m_UserState = State;
m_Successors.push_back( node );
return true;
}
return false;
}
// Free the solution nodes
// This is done to clean up all used Node memory when you are done with the
// search
void FreeSolutionNodes()
{
Node *n = m_Start;
if ( m_Start->child )
{
do
{
Node *del = n;
n = n->child;
FreeNode( del );
del = NULL;
} while( n != m_Goal );
FreeNode( n ); // Delete the goal
}
else
{
// if the start node is the solution we need to just delete the start and goal
// nodes
FreeNode( m_Start );
FreeNode( m_Goal );
}
}
// Functions for traversing the solution
// Get start node
UserState *GetSolutionStart()
{
m_CurrentSolutionNode = m_Start;
if ( m_Start )
{
return &m_Start->m_UserState;
}
else
{
return NULL;
}
}
// Get next node
UserState *GetSolutionNext()
{
if ( m_CurrentSolutionNode )
{
if ( m_CurrentSolutionNode->child )
{
Node *child = m_CurrentSolutionNode->child;
m_CurrentSolutionNode = m_CurrentSolutionNode->child;
return &child->m_UserState;
}
}
return NULL;
}
// Get end node
UserState *GetSolutionEnd()
{
m_CurrentSolutionNode = m_Goal;
if ( m_Goal )
{
return &m_Goal->m_UserState;
}
else
{
return NULL;
}
}
// Step solution iterator backwards
UserState *GetSolutionPrev()
{
if ( m_CurrentSolutionNode )
{
if ( m_CurrentSolutionNode->parent )
{
Node *parent = m_CurrentSolutionNode->parent;
m_CurrentSolutionNode = m_CurrentSolutionNode->parent;
return &parent->m_UserState;
}
}
return NULL;
}
// For educational use and debugging it is useful to be able to view
// the open and closed list at each step, here are two functions to allow that.
UserState *GetOpenListStart()
{
int f,g,h;
return GetOpenListStart( f,g,h );
}
UserState *GetOpenListStart( int &f, int &g, int &h )
{
iterDbgOpen = m_OpenList.begin();
if ( iterDbgOpen != m_OpenList.end() )
{
f = (*iterDbgOpen)->f;
g = (*iterDbgOpen)->g;
h = (*iterDbgOpen)->h;
return &(*iterDbgOpen)->m_UserState;
}
return NULL;
}
UserState *GetOpenListNext()
{
int f,g,h;
return GetOpenListNext( f,g,h );
}
UserState *GetOpenListNext( int &f, int &g, int &h )
{
iterDbgOpen++;
if ( iterDbgOpen != m_OpenList.end() )
{
f = (*iterDbgOpen)->f;
g = (*iterDbgOpen)->g;
h = (*iterDbgOpen)->h;
return &(*iterDbgOpen)->m_UserState;
}
return NULL;
}
UserState *GetClosedListStart()
{
int f,g,h;
return GetClosedListStart( f,g,h );
}
UserState *GetClosedListStart( int &f, int &g, int &h )
{
iterDbgClosed = m_ClosedList.begin();
if ( iterDbgClosed != m_ClosedList.end() )
{
f = (*iterDbgClosed)->f;
g = (*iterDbgClosed)->g;
h = (*iterDbgClosed)->h;
return &(*iterDbgClosed)->m_UserState;
}
return NULL;
}
UserState *GetClosedListNext()
{
int f,g,h;
return GetClosedListNext( f,g,h );
}
UserState *GetClosedListNext( int &f, int &g, int &h )
{
iterDbgClosed++;
if ( iterDbgClosed != m_ClosedList.end() )
{
f = (*iterDbgClosed)->f;
g = (*iterDbgClosed)->g;
h = (*iterDbgClosed)->h;
return &(*iterDbgClosed)->m_UserState;
}
return NULL;
}
// Get the number of steps
int GetStepCount() { return m_Steps; }
void EnsureMemoryFreed()
{
#if USE_FSA_MEMORY
assert(m_AllocateNodeCount == 0);
#endif
}
private: // methods
// This is called when a search fails or is cancelled to free all used
// memory
void FreeAllNodes()
{
// iterate open list and delete all nodes
typename vector< Node * >::iterator iterOpen = m_OpenList.begin();
while( iterOpen != m_OpenList.end() )
{
Node *n = (*iterOpen);
FreeNode( n );
iterOpen ++;
}
m_OpenList.clear();
// iterate closed list and delete unused nodes
typename vector< Node * >::iterator iterClosed;
for ( iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed ++ )
{
Node *n = (*iterClosed);
FreeNode( n );
}
m_ClosedList.clear();
// delete the goal
FreeNode(m_Goal);
}
// This call is made by the search class when the search ends. A lot of nodes may be
// created that are still present when the search ends. They will be deleted by this
// routine once the search ends
void FreeUnusedNodes()
{
// iterate open list and delete unused nodes
typename vector< Node * >::iterator iterOpen = m_OpenList.begin();
while( iterOpen != m_OpenList.end() )
{
Node *n = (*iterOpen);
if ( !n->child )
{
FreeNode( n );
n = NULL;
}
iterOpen ++;
}
m_OpenList.clear();
// iterate closed list and delete unused nodes
typename vector< Node * >::iterator iterClosed;
for ( iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed ++ )
{
Node *n = (*iterClosed);
if ( !n->child )
{
FreeNode( n );
n = NULL;
}
}
m_ClosedList.clear();
}
// Node memory management
Node *AllocateNode()
{
#if !USE_FSA_MEMORY
Node *p = new Node;
return p;
#else
Node *address = m_FixedSizeAllocator.Alloc();
if ( !address )
{
return NULL;
}
m_AllocateNodeCount ++;
Node *p = new (address) Node;
return p;
#endif
}
void FreeNode( Node *node )
{
m_AllocateNodeCount --;
#if !USE_FSA_MEMORY
delete node;
#else
m_FixedSizeAllocator.Free( node );
#endif
}
private: // data
// Heap (simple vector but used as a heap, cf. Steve Rabin's game gems article)
vector< Node *> m_OpenList;
// Closed list is a vector.
vector< Node * > m_ClosedList;
// Successors is a vector filled out by the user each type successors to a node
// are generated
vector< Node * > m_Successors;
// State
unsigned int m_State;
// Counts steps
int m_Steps;
// Start and goal state pointers
Node *m_Start;
Node *m_Goal;
Node *m_CurrentSolutionNode;
#if USE_FSA_MEMORY
// Memory
ObjPool<Node>m_FixedSizeAllocator;
//FixedSizeAllocator<Node> m_FixedSizeAllocator;
#endif
//Debug : need to keep these two iterators around
// for the user Dbg functions
typename vector< Node * >::iterator iterDbgOpen;
typename vector< Node * >::iterator iterDbgClosed;
// debugging : count memory allocation and free's
int m_AllocateNodeCount;
bool m_CancelRequest;
};

View File

@@ -0,0 +1,65 @@
#include <stdlib.h>
#include <stdio.h>
#include "os_def.h"
#include "_ast.h"
#include "x_thread.h"
#include "x_tick.h"
#include "x_lock.h"
#include "container/queue_list.h"
#include "net/base_socket.h"
#include "share_util.h"
#include "memory/buffer_allocator.h"
#include "gate_proto.h"
#include "server_def.h"
#include "appitnmsg.h"
#include "data_packet.hpp"
#include "net/send_packet_pool.h"
#include "net/work_socket.h"
#include "net/net_session.h"
#include "net/server_socket.h"
#include "gate_user.h"
#include "gate_session.h"
#include "gate_manager.h"
GateManager::GateManager(const char* name) : Inherited(name)
{
ZeroMemory(gate_list_, sizeof(gate_list_));
}
GateManager::~GateManager()
{
}
bool GateManager::Startup()
{
for (int i = 0; i < MaxGateCount; ++i)
{
gate_list_[i]->gate_idx_ = i;
}
return Inherited::Startup();
}
NetSession* GateManager::NewSession(SOCKET s, sockaddr_in* addrIn)
{
for (int i = 0; i < MaxGateCount; ++i)
{
if (!gate_list_[i]->connected())
{
gate_list_[i]->SetClientSocket(s, addrIn);
gate_list_[i]->ClearSendBuffers();
OutputMsg(rmError, "new gate connect,idx=%d", gate_list_[i]->gate_idx_);
return gate_list_[i];
}
}
return NULL;
}
void GateManager::DestroySession(NetSession*)
{
}

View File

@@ -0,0 +1,60 @@
#ifndef _GATE_MANAGER_H_
#define _GATE_MANAGER_H_
class GateSession;
using namespace container;
class GateManager
: public ServerSocket
{
public:
typedef ServerSocket Inherited;
static const int MaxGateCount = 1;
public:
GateManager(const char* name);
~GateManager();
virtual void Initialize() = 0;
virtual void Uninitialize() = 0;
bool Startup();
inline GateSession* GetGate(int idx)
{
if (idx >= 0 && idx < (int)ArrayCount(gate_list_))
return gate_list_[idx];
return NULL;
}
inline GateUser* GetUser(NetId& netid)
{
GateSession* gate = GetGate(netid.gate_id_);
return gate ? gate->GetUser(netid) : NULL;
}
inline void PostCloseUser(NetId& netid, const char* reason, int p1 = 0, int p2 = 0)
{
OutputMsg(rmError, "GateManager::PostCloseUser %s:%d:%d", reason ? reason : "", p1, p2);
GateSession* gate = GetGate(netid.gate_id_);
if (gate)
{
gate->PostCloseUser(netid, 0, reason, p1, p2);
}
}
protected:
NetSession* NewSession(SOCKET socket, sockaddr_in* addrin);
void DestroySession(NetSession* client);
protected:
GateSession* gate_list_[MaxGateCount]; //Íø¹ØÁбí
};
#endif

View File

@@ -0,0 +1,28 @@
#ifndef _GATE_PROTO_H_
#define _GATE_PROTO_H_
/********************************************************
* 网关与内部服务器通信协议以及基础数据结构定义
**********************************************************/
#define GW_OPEN 1 //打开新用户会话,当客户端连接到网关时网关向服务器发送此消息
#define GW_CLOSE 2 //关闭用户会话,当客户端与网关的链接断开时网关向服务器发送此消息
//#define GW_CHECKSERVER 3 //网关回应服务器的心跳包消息
//#define GW_CHECKCLIENT 4 //服务器向网关发送心跳包消息
#define GW_DATA 5 //网关转发用户通信数据到服务器,服务器向网关发送用户通信数据也使用此消息
#define GW_CHANNEL 6 //同步频道的信息
#define GW_TEST 1026 // 用于测试网关和服务器之间的链路是否丢包
#define GW_CMD 1027
enum
{
ccAddUser = 1, // 增加用户
ccDelUser = 2, // 删除用户
ccBroadCast = 3, // 广播
};
#endif

View File

@@ -0,0 +1,207 @@
#include <stdio.h>
#include <stdlib.h>
#include "os_def.h"
#include "_ast.h"
#include "container/queue_list.h"
#include "x_tick.h"
#include "x_lock.h"
#include "x_thread.h"
#include "net/base_socket.h"
#include "server_def.h"
#include "gate_proto.h"
#include "share_util.h"
#include "memory/buffer_allocator.h"
#include "appitnmsg.h"
#include "data_packet.hpp"
#include "data_packet_reader.hpp"
#include "net/send_packet_pool.h"
#include "net/work_socket.h"
#include "net/net_session.h"
#include "net/server_socket.h"
#include "gate_user.h"
#include "gate_session.h"
#include "gate_manager.h"
GateSession::GateSession(const char* name) : Inherited(name)
{
gate_idx_ = 0;
}
GateSession::~GateSession()
{
CloseAllUser();
FreeBuffers();
}
void GateSession::FreeBuffers()
{
ClearSendList();
}
DataPacket& GateSession::AllocGateSendPacket(uint16_t cmd, NetId& netid)
{
DataPacket& packet = Inherited::allocProtoPacket(cmd);
packet << netid;
return packet;
}
DataPacket& GateSession::AllocGateSendPacket(NetId& netid)
{
DataPacket& packet = Inherited::allocProtoPacket(GW_DATA);
packet << netid;
return packet;
}
void GateSession::Disconnected()
{
Inherited::Disconnected();
FreeBuffers();
CloseAllUser();
}
void GateSession::OnRecvSysMsg(unsigned int msg, size_t p1, size_t p2, size_t p3, size_t p4)
{
switch (msg)
{
case CLOSE_GATE_SESSION:
// 这是由系统内部发出的关闭命令
NetId netid;
netid.socket_ = MAKEINT64(p1, p2);
netid.index_ = LOINT16(p3);
netid.gate_id_ = HIINT16(p3);
CloseUser(netid, "OnRecvSysMsg");
SendGateCloseUser(netid);
break;
}
}
void GateSession::OnRecv(const uint16_t cmd, char* buf, int size)
{
if (size < (int)sizeof(NetId) || buf == NULL) return;
NetId* netid = (NetId*)buf;
buf += sizeof(NetId);
size -= sizeof(NetId);
if (netid->index_ >= MAX_GATE_USER) return;
GateUser& user = user_list_[netid->index_];
netid->gate_id_ = (uint16_t)gate_idx_;
switch (cmd)
{
case GW_OPEN:
{
OpenNewUser(*netid, buf);
break;
}
case GW_CLOSE:
{
CloseUser(*netid, "GW_CLOSE");
break;
}
case GW_DATA:
{
if (!user.closed_ && user.netid_.socket_ == netid->socket_)
{
OnRecv(*netid, buf, size);
}
break;
}
case GW_TEST:
case GW_CMD:
{
// 原样数据返回
DataPacket& packet = AllocGateSendPacket(cmd, *netid);
packet.writeBuf(buf, size);
flushProtoPacket(packet);
break;
}
}
}
NetId* GateSession::OpenNewUser(NetId& netid, const char* addr)
{
if (netid.index_ >= MAX_GATE_USER) return NULL;
GateUser& user = user_list_[netid.index_];
user.netid_ = netid;
user.netid_.gate_id_ = (uint16_t)gate_idx_;
user.account_id_ = 0;
_STRNCPY_A(user.remote_addr_, addr);
user.closed_ = false;
user.account_name_[0] = 0;
user.gm_ = -1;
OnOpenUser(&user);
return &user.netid_;
}
void GateSession::OnOpenUser(GateUser*)
{
}
void GateSession::OnCloseUser(GateUser*, const char* reason)
{
}
bool GateSession::CloseUser(NetId& netid, const char* reason)
{
if (netid.index_ >= MAX_GATE_USER) return false;
if (netid.gate_id_ != gate_idx_) return false;
GateUser& user = user_list_[netid.index_];
if (user.closed_ == true) return true;
if (user.netid_.socket_ != netid.socket_) return false;
user.closed_ = true;
OnCloseUser(&user, reason);
return true;
}
void GateSession::CloseAllUser()
{
for (int i = 0; i < MAX_GATE_USER; i++)
{
GateUser& user = user_list_[i];
CloseUser(user.netid_, "CloseAllUser");
}
}
void GateSession::SendGateCloseUser(NetId& netid)
{
OutputMsg(rmNormal, ("close Socket=%d, GateSessionIdx=%d,reason=GW_CLOSE"), netid.socket_, netid.index_);
DataPacket& packet = AllocGateSendPacket(GW_CLOSE, netid);
flushProtoPacket(packet);
}
bool GateSession::OnValidateRegData(const SrvDef::PSERVER_REGDATA regData)
{
return (regData && regData->GameType == SrvDef::SERVER_REGDATA::GT_ID && regData->ServerType == SrvDef::GateServer);
}
GateUser* GateSession::GetUser(NetId& netid)
{
if (netid.index_ >= MAX_GATE_USER) return NULL;
if (netid.gate_id_ != gate_idx_) return NULL;
return &user_list_[netid.index_];
}

View File

@@ -0,0 +1,63 @@
#ifndef _GATE_CONNECTION_H_
#define _GATE_CONNECTION_H_
class GateManager;
class GateUser;
using namespace container;
class GateSession
: public NetSession
{
friend class GateManager;
public:
typedef NetSession Inherited;
public:
DataPacket& AllocGateSendPacket(uint16_t cmd, NetId& netid);
DataPacket& AllocGateSendPacket(NetId& netid);
inline void PostCloseUser(NetId& netid, int accountId, const char* reason, int p1 = 0, int p2 = 0)
{
OutputMsg(rmError, "GateSession::PostCloseUser %s:%d:%d", reason ? reason : "", p1, p2);
PostMsg(CLOSE_GATE_SESSION, LOINT32(netid.socket_), HIINT32(netid.socket_), MAKEINT32(netid.index_, netid.gate_id_), accountId);
}
GateUser* GetUser(NetId& netid);
protected:
virtual void OnOpenUser(GateUser* user);
virtual void OnCloseUser(GateUser* user, const char* reason);
virtual bool OnValidateRegData(const SrvDef::PSERVER_REGDATA regData);
protected:
void Disconnected();
void OnRecvSysMsg(unsigned int msg, size_t p1, size_t p2, size_t p3, size_t p4);
virtual void OnRecv(const uint16_t cmd, char* buf, int size);
NetId* OpenNewUser(NetId& netid, const char* addr);
bool CloseUser(NetId& netid, const char* reason);
void CloseAllUser();
virtual void OnRecv(NetId& netid, char* buf, int size) = 0;
void SendGateCloseUser(NetId& netid);
void FreeBuffers();
public:
GateSession(const char* name);
~GateSession();
protected:
static const int MAX_GATE_USER = 8192; //最大网关用户数
static const unsigned int CLOSE_GATE_SESSION = 102;
int gate_idx_; //网关编号
GateUser user_list_[MAX_GATE_USER];
};
#endif

View File

@@ -0,0 +1,26 @@
#ifndef _GATE_USER_H_
#define _GATE_USER_H_
class GateUser
{
public:
NetId netid_;
int account_id_; //网关用户的全局会话ID
ActorId actor_id_; // 选择的角色id在此之前是0
bool closed_; //是否标记为主动关闭
int64_t handle_;
int gm_; // gm等级
char remote_addr_[32]; //客户端地址
SrvDef::ACCOUNT account_name_; //帐号字符串
public:
GateUser(): account_id_(0), actor_id_(0), closed_(true), handle_(0), gm_(-1)
{
STATIC_ASSERT(sizeof(netid_.index_) == 2);
netid_.index_ = 0xffff;
remote_addr_[0] = 0;
account_name_[0] = 0;
}
};
#endif

View File

@@ -0,0 +1,203 @@
#ifndef _LOG_TYPE_H_
#define _LOG_TYPE_H_
using namespace SrvDef;
// new
enum LogMsgCmd
{
lmCounter = 1,
lmInstall = 2,
lmDau = 3,
lmEconomy = 4,
lmMilestone = 5,
lmCounterDB = 6,
lmPayment = 7,
lmGameInfo = 8,
lmOnline = 9, // 统计在线人数
lmDcApiData = 10, //QQ统一数据平台接口
lmDcApiDataList = 11, //QQ统一数据平台接口
lmDcApiProto = 12, //QQ统一数据平台接口(接口6.20)
lmTLog = 13, // 发送到TLog数据
lmChat = 14, // 统计聊天信息
lmDKMLog = 15, //多可梦日志报送
};
enum LogFlagInter
{
lfiDB = 1, // 保存数据库
lfiBI = 2, // 保存到BI
lfiText = 4, // 保存到文本
lfiIsPay = 8, // 是否充值的数据
};
struct LDcApiLogTable
{
char key_[16];
char value_[64];
bool mustUrlencode_;
};
typedef Vector<LDcApiLogTable*, 128> LDcApiLogTableList;
struct LDcApiData
{
char log_name_[128];
short log_type_; // 见《DC_API_manual_C++_V2.1.pdf》中日志类型定义 : 0=经分数据上报1=模调数据上报4=反外挂数据上报
char content_[2048];
};
struct LDcApiProtoLog
{
//=====head=====
char openId[128]; //即玩家帐号
int domain; //平台ID
int serverId;
char svrip[32]; //服务器ip
char userip[32]; //用户ip
//=====end head=====
//===body=====
int roleId;
int protoId;
int gameFeatrueId; //直接填写系统ID
int protoType;
int protoResult;
//===end body====
};
struct LCounter
{
ActorId actorid_;
char aid_[64];
char user_level_[32];
char counter_[32];
char value_[32];
char extra_[128];
char kingdom_[32];
char phylum_[32];
char classfield_[32];
char family_[32];
char genus_[128];
bool save_db_; // 是否保存到本地数据库,这个已经没用
int flag_;
};
struct LInstall
{
char aid_[64];
char source_[32];
char affiliate_[32];
char creative_[32];
char family_[32];
char genus_[32];
char from_uid_[32];
char extra_[32];
int flag_;
};
struct LDau
{
char aid_[64];
char source_[32];
char affiliate_[32];
char creative_[32];
char family_[32];
char genus_[32];
char ip_[32];
char from_uid_[32];
char extra_[32];
int flag_;
};
struct LEconomy
{
ActorId actorid_;
char aid_[64];
char currency_[32]; // currency type
char amount_[32]; //numerical amount
char value_[32]; // numerical value
char kingdom_[32];
char phylum_[32];
char classfield_[32];
char family_[32];
char genus_[32];
char extra_[128];
char extra2_[32];
char pf_[128];
int flag_;
char openkey_[512];
char pfkey_[128];
char pfid_[128];
};
struct LMilestone
{
ActorId actorid_;
char aid_[64];
char milestone_[32];
char value_[32];
char extra_[32];
int flag_;
};
struct LPayment
{
ActorId actorId_;
char aid_[64];
int amount_;
int value_;
char kingdom_[32];
char phylum_[32];
char transactionid_[32];
char extra_[32];
int mstType_;
int p1_;
int p2_;
int p3_;
int p4_;
int p5_;
int ret_;
int flag_;
};
struct LGameInfo
{
char aid_[64];
char user_level_[32];
char value_[32];
char extra_[32];
char kingdom_[32];
char phylum_[32];
char classfield_[32];
char family_[32];
char genus_[32];
int flag_;
};
struct LChat
{
ActorId actorid_;
char aid_[64];
char name_[32];
char ip_[32];
char pf_[32];
int type_;
char toaid_[64];
char toname_[32];
char content_[1024];
};
enum ChatType
{
ctSecret = 1, // 私聊,密语
ctMail = 3,
ctWorld = 4, // 世界,喇叭频道
ctCamp = 5,
ctGuild = 6, // 工会,帮派
ctTeam = 7, // 队伍频道,5人
ctNear = 8, // (取消)附近频道,同屏
ctOther = 9,
};
#endif

View File

@@ -0,0 +1,641 @@
#include <stdlib.h>
#include <stdio.h>
#include "os_def.h"
#include "_ast.h"
#include "x_tick.h"
#include "x_lock.h"
#include "container/queue_list.h"
#include "net/base_socket.h"
#include "share_util.h"
#include "memory/buffer_allocator.h"
#include "appitnmsg.h"
#include "data_packet.hpp"
#include "net/send_packet_pool.h"
#include "net/work_socket.h"
#include "net/net_client.h"
#include "server_def.h"
#include "log_def.h"
#include "encrypt/CRC.h"
#include "encrypt/Encrypt.h"
#include "log_sender.h"
using namespace SrvDef;
LogSender::LogSender(int ServerType, int ServerIndex, char* ServerName) : NetClient("LogSender")
{
this->ServerType = ServerType;
this->ServerIndex = ServerIndex;
_STRNCPY_A(this->ServerName, ServerName);
this->SetClientName(("logger server"));
stop_log_ = false;
stop_counter_log_ = false;
stop_economy_log_ = false;
}
LogSender::LogSender() : NetClient("LogSender")
{
this->SetClientName(("logger server"));
stop_log_ = false;
stop_counter_log_ = false;
stop_economy_log_ = false;
}
LogSender::~LogSender(void)
{
}
void LogSender::SetServerName(const char* sServerName)
{
_STRNCPY_S(ServerName, sServerName, ArrayCount(ServerName) - 1);
ServerName[ArrayCount(ServerName) - 1] = 0;
}
int LogSender::GetLocalServerType()
{
return ServerType;
}
const char* LogSender::GetLocalServerName()
{
return ServerName;
}
int LogSender::GetLocalServerIndex()
{
return ServerIndex;
}
void LogSender::OnConnected()
{
setRecvBufSize(1024 * 1024);
setSendBufSize(1024 * 1024);
}
void LogSender::LogCounter(ActorId actorId, const char* aid, const char* user_level /*= ""*/,
const char* counter /*= ""*/, const char* value /*= ""*/, const char* extra /*= ""*/,
const char* kingdom /*= ""*/, const char* phylum /*= ""*/, const char* classfield /*= ""*/,
const char* family /*= ""*/, const char* genus /*= ""*/, int flag)
{
if (stop_log_ || stop_counter_log_) return;
LCounter data;
memset(&data, 0, sizeof(data));
data.actorid_ = actorId;
data.flag_ = flag;
if (aid)
{
_STRNCPY_A(data.aid_, aid);
}
if (user_level)
{
_STRNCPY_A(data.user_level_, user_level);
}
if (counter)
{
_STRNCPY_A(data.counter_, counter);
}
if (value)
{
_STRNCPY_A(data.value_, value);
}
if (extra)
{
_STRNCPY_A(data.extra_, extra);
}
if (kingdom)
{
_STRNCPY_A(data.kingdom_, kingdom);
}
if (phylum)
{
_STRNCPY_A(data.phylum_, phylum);
}
if (classfield)
{
_STRNCPY_A(data.classfield_, classfield);
}
if (family)
{
_STRNCPY_A(data.family_, family);
}
if (genus)
{
_STRNCPY_A(data.genus_, genus);
}
DataPacket& pdata = allocProtoPacket(lmCounter);
pdata << data;
flushProtoPacket(pdata);
}
void LogSender::LogDcApiLogByStr(const char* logName, const char* logContent)
{
if (stop_log_) return;
if(!logName || !logContent) return;
LDcApiData data;
memset(&data, 0, sizeof(data));
data.log_type_ = 4;
_STRNCPY_A(data.log_name_, logName);
_STRNCPY_A(data.content_ ,logContent);
DataPacket& pdata = allocProtoPacket(lmDcApiData);
pdata << data;
flushProtoPacket(pdata);
}
void LogSender::LogDcApiProto(const char* openId, int pfId, int serverId, int roleId, int systemId, int protoId, int protoType, int protoResult, const char* svrip, const char* userip)
{
//if (!et || ((Entity*)et)->GetType() != enActor)
// return;
//Actor* pActor =(Entity*)et;
if (stop_log_) return;
if(!openId) return;
LDcApiProtoLog logData;
memset(&logData, 0, sizeof(logData));
//_STRNCPY_A(logData.openId, pActor->GetAccount());
_STRNCPY_A(logData.openId, openId);
logData.domain = pfId;
//logData.serverId = ServerInstance()->GetServerIndex();
logData.serverId = serverId;
_STRNCPY_A(logData.svrip, svrip);
_STRNCPY_A(logData.userip, userip);
//logData.roleId = pActor->GetActorId();
logData.roleId = roleId;
logData.protoId = MAKEINT16(protoId, systemId);
logData.gameFeatrueId = systemId;
logData.protoType = protoType;
logData.protoResult = protoResult;
DataPacket& pdata = allocProtoPacket(lmDcApiProto);
pdata << logData;
flushProtoPacket(pdata);
}
void LogSender::LogInstall(const char* aid, const char* source /*= ""*/,
const char* affiliate /*= ""*/, const char* creative /*= ""*/,
const char* family /*= ""*/, const char* genus /*= ""*/,
const char* from_uid /*= ""*/ , const char* extra, int flag/* = 3*/)
{
if (stop_log_) return;
LInstall data;
memset(&data, 0, sizeof(data));
data.flag_ = flag;
if (aid)
{
_STRNCPY_A(data.aid_, aid);
}
if (source)
{
_STRNCPY_A(data.source_, source);
}
if (affiliate)
{
_STRNCPY_A(data.affiliate_, affiliate);
}
if (creative)
{
_STRNCPY_A(data.creative_, creative);
}
if (family)
{
_STRNCPY_A(data.family_, family);
}
if (genus)
{
_STRNCPY_A(data.genus_, genus);
}
if (from_uid)
{
_STRNCPY_A(data.from_uid_, from_uid);
}
if (extra)
{
_STRNCPY_A(data.extra_, extra);
}
DataPacket& pdata = allocProtoPacket(lmInstall);
pdata << data;
flushProtoPacket(pdata);
}
void LogSender::LogDau(const char* aid, const char* source /*= ""*/,
const char* affiliate /*= ""*/, const char* creative /*= ""*/,
const char* family /*= ""*/, const char* genus /*= ""*/,
const char* ip /*= ""*/, const char* from_uid /*= ""*/, const char* extra, int flag/* = 3*/)
{
if (stop_log_) return;
LDau data;
memset(&data, 0, sizeof(data));
data.flag_ = flag;
if (aid)
{
_STRNCPY_A(data.aid_, aid);
}
if (source)
{
_STRNCPY_A(data.source_, source);
}
if (affiliate)
{
_STRNCPY_A(data.affiliate_, affiliate);
}
if (creative)
{
_STRNCPY_A(data.creative_, creative);
}
if (family)
{
_STRNCPY_A(data.family_, family);
}
if (genus)
{
_STRNCPY_A(data.genus_, genus);
}
if (ip)
{
_STRNCPY_A(data.ip_, ip);
}
if (from_uid)
{
_STRNCPY_A(data.from_uid_, from_uid);
}
if (extra)
{
_STRNCPY_A(data.extra_, extra);
}
DataPacket& pdata = allocProtoPacket(lmDau);
pdata << data;
flushProtoPacket(pdata);
}
void LogSender::LogEnconomy(ActorId actorid, const char* aid, const char* currency /*= ""*/,
const char* amount /*= ""*/, const char* value /*= ""*/,
const char* kingdom /*= ""*/, const char* phylum /*= ""*/,
const char* classfield /*= ""*/, const char* family /*= ""*/,
const char* genus /*= ""*/ , const char* extra, const char* extra2, const char* pf, int flag/* = 3*/,
bool isPay, const char* openkey, const char* pfkey, const char* pfid)
{
if (stop_log_ || stop_economy_log_) return;
LEconomy data;
memset(&data, 0, sizeof(data));
data.flag_ = flag;
data.flag_ |= (isPay ? lfiIsPay : 0);
data.actorid_ = actorid;
if (aid)
{
_STRNCPY_A(data.aid_, aid);
}
if (currency)
{
_STRNCPY_A(data.currency_, currency);
}
if (amount)
{
_STRNCPY_A(data.amount_, amount);
}
if (value)
{
_STRNCPY_A(data.value_, value);
}
if (kingdom)
{
_STRNCPY_A(data.kingdom_, kingdom);
}
if (phylum)
{
_STRNCPY_A(data.phylum_, phylum);
}
if (classfield)
{
_STRNCPY_A(data.classfield_, classfield);
}
if (family)
{
_STRNCPY_A(data.family_, family);
}
if (genus)
{
_STRNCPY_A(data.genus_, genus);
}
if (extra)
{
_STRNCPY_A(data.extra_, extra);
}
if (extra2)
{
_STRNCPY_A(data.extra2_, extra2);
}
if (pf)
{
_STRNCPY_A(data.pf_, pf);
}
if (openkey)
{
_STRNCPY_A(data.openkey_, openkey);
}
if (pfkey)
{
_STRNCPY_A(data.pfkey_, pfkey);
}
if (pfid) {
_STRNCPY_A(data.pfid_, pfid);
}
DataPacket& pdata = allocProtoPacket(lmEconomy);
pdata << data;
flushProtoPacket(pdata);
}
void LogSender::LogMilestone(ActorId actorid, const char* aid, const char* milestone /*= ""*/, const char* value /*= ""*/, const char* extra, int flag/* = 3*/)
{
if (stop_log_) return;
LMilestone data;
memset(&data, 0, sizeof(data));
data.flag_ = flag;
data.actorid_ = actorid;
if (aid)
{
_STRNCPY_A(data.aid_, aid);
}
if (milestone)
{
_STRNCPY_A(data.milestone_, milestone);
}
if (value)
{
_STRNCPY_A(data.value_, value);
}
if (extra)
{
_STRNCPY_A(data.extra_, extra);
}
DataPacket& pdata = allocProtoPacket(lmMilestone);
pdata << data;
flushProtoPacket(pdata);
}
void LogSender::LogPayment(int ret, ActorId actorId, const char* aid, int amount,
int mstType, int p1, int p2, int p3,
int value /*= 1*/, const char* kingdom /*= ""*/, const char* phylum /*= ""*/, const char* transactionid /*= ""*/,
const char* extra /*= ""*/, int p4 /*= 0*/, int p5 /*= 0*/, int flag/* = 3*/)
{
if (stop_log_) return;
LPayment data;
memset(&data, 0, sizeof(data));
data.ret_ = ret;
data.actorId_ = actorId;
data.amount_ = amount;
data.value_ = value;
data.mstType_ = mstType;
data.p1_ = p1;
data.p2_ = p2;
data.p3_ = p3;
data.p4_ = p4;
data.p5_ = p5;
data.flag_ = flag;
if (aid)
{
_STRNCPY_A(data.aid_, aid);
}
if (kingdom)
{
_STRNCPY_A(data.kingdom_, kingdom);
}
if (phylum)
{
_STRNCPY_A(data.phylum_, phylum);
}
if (transactionid)
{
_STRNCPY_A(data.transactionid_, transactionid);
}
if (extra)
{
_STRNCPY_A(data.extra_, extra);
}
DataPacket& pdata = allocProtoPacket(lmPayment);
pdata << data;
flushProtoPacket(pdata);
}
void LogSender::LogGameInfo(const char* aid, const char* user_level /*= ""*/,
const char* value /*= ""*/, const char* extra /*= ""*/, const char* kingdom /*= ""*/,
const char* phylum /*= ""*/, const char* classfield /*= ""*/, const char* family /*= ""*/,
const char* genus /*= ""*/,
int flag/* = 3*/)
{
if (stop_log_) return;
LGameInfo data;
memset(&data, 0, sizeof(data));
data.flag_ = flag;
if (aid)
{
_STRNCPY_A(data.aid_, aid);
}
if (user_level)
{
_STRNCPY_A(data.user_level_, user_level);
}
if (value)
{
_STRNCPY_A(data.value_, value);
}
if (extra)
{
_STRNCPY_A(data.extra_, extra);
}
if (kingdom)
{
_STRNCPY_A(data.kingdom_, kingdom);
}
if (phylum)
{
_STRNCPY_A(data.phylum_, phylum);
}
if (classfield)
{
_STRNCPY_A(data.classfield_, classfield);
}
if (family)
{
_STRNCPY_A(data.family_, family);
}
if (genus)
{
_STRNCPY_A(data.genus_, genus);
}
DataPacket& pdata = allocProtoPacket(lmGameInfo);
pdata << data;
flushProtoPacket(pdata);
}
void LogSender::LogChat(const char* aid, const char* name, const char* ip, const char* pf, int actorid, int type,
const char* content, const char* toaid /* = "" */, const char* toname /* = "" */)
{
if (stop_log_) return;
LChat data;
memset(&data, 0, sizeof(data));
if (aid)
{
_STRNCPY_A(data.aid_, aid);
}
if (name)
{
_STRNCPY_A(data.name_, name);
}
if (pf)
{
_STRNCPY_A(data.pf_, pf);
}
if (ip)
{
_STRNCPY_A(data.ip_, ip);
}
data.type_ = type;
data.actorid_ = actorid;
if (content)
{
_STRNCPY_A(data.content_, content);
}
if (toaid)
{
_STRNCPY_A(data.toaid_, toaid);
}
if (toname)
{
_STRNCPY_A(data.toname_, toname);
}
DataPacket& pdata = allocProtoPacket(lmChat);
pdata << data;
flushProtoPacket(pdata);
}
void LogSender::LogOnline(int cnt, int extra)
{
if (stop_log_) return;
DataPacket& pdata = allocProtoPacket(lmOnline);
pdata << (int)cnt;
pdata << (int)extra;
flushProtoPacket(pdata);
}
void LogSender::LogTLog(const char* logstr)
{
if (stop_log_) return;
DataPacket& pdata = allocProtoPacket(lmTLog);
pdata.writeString(logstr);
flushProtoPacket(pdata);
}
void LogSender::LogDKMLog(const char* logstr, const char* pf)
{
if (!logstr || !pf) return;
if (stop_log_) return;
DataPacket& pdata = allocProtoPacket(lmDKMLog);
pdata.writeString(logstr);
pdata.writeString(pf);
flushProtoPacket(pdata);
}

View File

@@ -0,0 +1,187 @@
#ifndef _LOG_SENDER_H_
#define _LOG_SENDER_H_
class NetClient;
class LogSender:
public NetClient
{
public:
// DC API日志
void LogDcApiLogByStr(const char* logName, const char* logContent);
// DC API游戏协议日志
void LogDcApiProto(const char* openId, int pf, int serverId, int roleId, int systemId, int protoId, int protoType, int protoResult, const char* svrip, const char* userip);
void LogCounter(ActorId actorid, const char* aid,
const char* user_level = "",
const char* counter = "",
const char* value = "",
const char* extra = "",
const char* kingdom = "",
const char* phylum = "",
const char* classfield = "",
const char* family = "",
const char* genus = "",
int flag = 1);
void LogInstall(const char* actorId, const char* source = "",
const char* affiliate = "",
const char* creative = "",
const char* family = "",
const char* genus = "",
const char* from_uid = "",
const char* extra = "",
int flag = 3);
void LogDau(const char* aid,
const char* source = "",
const char* affiliate = "",
const char* creative = "",
const char* family = "",
const char* genus = "",
const char* ip = "",
const char* from_uid = "",
const char* extra = "",
int flag = 3);
void LogEnconomy(ActorId actorid, const char* aid,
const char* currency = "",
const char* amount = "",
const char* value = "",
const char* kingdom = "",
const char* phylum = "",
const char* classfield = "",
const char* family = "",
const char* genus = "",
const char* extra = "",
const char* extra2 = "",
const char* pf = "",
int flag = 3,
bool isPay = true,
const char* openkey = "",
const char* pfkey = "", const char* pfid = ""); // 表示是否充值的数据
void LogMilestone(
ActorId actorid,
const char* aid,
const char* milestone = "",
const char* value = "",
const char* extra = "",
int flag = 3);
void LogPayment(int ret, ActorId actorId, const char* aid, int amount,
int mstType,
int p1,
int p2,
int p3,
int value = 1,
const char* kingdom = "",
const char* phylum = "",
const char* transactionid = "",
const char* extra = "",
int p4 = 0,
int p5 = 0,
int flag = 3);
void LogGameInfo(const char* aid,
const char* user_level = "",
const char* value = "",
const char* extra = "",
const char* kingdom = "",
const char* phylum = "",
const char* classfield = "",
const char* family = "",
const char* genus = "",
int flag = 3);
void LogChat(const char* aid,
const char* name,
const char* ip,
const char* pf,
ActorId actorid,
int type,
const char* content,
const char* toaid = "",
const char* toname = "");
// 记录在线人数
void LogOnline(int cnt, int extra);
void LogTLog(const char* logstr);
void LogDKMLog(const char* logstr, const char* pf = "0");
inline int GetServerIndex()
{
return ServerIndex;
}
inline int GetServerType()
{
return ServerType;
}
inline const char* GetServerName()
{
return ServerName;
}
void SetServerIndex(const int nSerIdx)
{
ServerIndex = nSerIdx;
}
void SetServerType(const int nSrvType)
{
ServerType = nSrvType;
}
void SetServerName(const char* sServerName);
// 是否停止记录日志
inline void StopLog(bool flag = true)
{
stop_log_ = flag;
}
inline void StopCounterLog(bool flag = true)
{
stop_counter_log_ = flag;
}
inline void StopEconomyLog(bool flag = true)
{
stop_economy_log_ = flag;
}
public:
LogSender();
LogSender(int ServerType, int ServerIndex, char* ServerName);
~LogSender(void);
protected:
// /*** 子类需覆盖的函数集 ***/
///* 处理单个通信数据包
// * nCmd 通信消息命令
// * inPacket 已经读取出通信命令的数据包,数据包的读取位置指向命令数据后的内容
// */
//virtual void OnRecv(const uint16_t cmd, DataPacketReader &data);
/*** 下列函数为子类可能有必要覆盖的函数集 ***/
/* ★查询本地服务器的类型,以便正确的发送注册数据 */
virtual int GetLocalServerType();
/* ★查询本地服务器的名称,以便正确的发送注册数据 */
virtual const char* GetLocalServerName();
/* ★查询本地服务器ID以便正确的发送注册数据默认的返回值是0 */
virtual int GetLocalServerIndex();
void OnConnected();
private:
//以下4个值用于发送注册包
int ServerType; //服务器类型值为SERVERTYPE枚举类型中的枚举值
int ServerIndex; //服务器唯一编号(服务器编号仅对游戏服务器有意义)
char ServerName[128]; //服务器名称需包含0终止符
bool stop_log_;
bool stop_counter_log_;
bool stop_economy_log_;
};
#endif

View File

@@ -0,0 +1,142 @@
#ifndef _LUA_SOCKET_HPP_
#define _LUA_SOCKET_HPP_
/******************************************************************
*封装一个简单的socket类给lua调用
*
*****************************************************************/
#include "net/base_socket.h"
using namespace net;
class LuaSocket : public BaseSocket
{
public:
LuaSocket(): buff_(NULL)
{
//printf("LuaSocket():%lld \n", (long long int)this);
}
virtual ~LuaSocket()
{
//printf("~LuaSocket():%lld \n", (long long int)this);
if (buff_)
{
free(buff_);
buff_ = NULL;
}
}
// 建立连接,暂时只支持阻塞模式
//通过32位IP地址连接到制定的端口返回值为socket错误号0表示成功。对于非阻塞模式返回0并不表示已经建立连接
int connect(const double addr, const int port, bool block = true)
{
unsigned long long d;
memcpy(&d, &addr, sizeof(addr));
return BaseSocket::connect((u_long)d, port, block);
}
//向套接字写入内容返回0表示连接已断开返回SOCKET_ERROR表示发生错误
//暂时只支持写入字符串可用于http协议
int send(char* buf)
{
if (!buf) return SOCKET_ERROR;
return BaseSocket::send((void*)buf, (int)strlen(buf));
}
const char* readline(int& retval)
{
retval = 0;
// 返回SOCKET_ERROR != retval && 0 != retval 表示还有数据可以读
const int max_size = 1024;
if (!buff_) buff_ = (char*)malloc(max_size);
retval = recv(buff_, max_size - 1, 0);
if (retval >= 0)
buff_[retval] = 0;
return buff_;
}
const char* readall(int& retval)
{
//printf("readall start:%lld \n", (long long int)this);
const int max_size = 1024;
int total = 0;
retval = 0;
for (;;)
{
total += max_size;
buff_ = (char*)(buff_ ? realloc(buff_, total) : malloc(total));
assert(buff_);
int len = recv(buff_ + retval, total - retval - 1);
if (len <= 0)
{
break;
}
else
{
retval += len;
if (retval < (total - 1)) break;
}
}
//printf("readall end:%lld \n", (long long int)this);
buff_[retval] = 0;
return buff_;
}
public:
static LuaSocket* NewSocket()
{
//printf("NewSocket threadid %d\n", (int)GetCurrentThreadId());
LuaSocket* s = new LuaSocket();
int err = createSocket(&s->socket_);
if (err)
{
delete s;
return NULL;
}
//printf("NewSocket:%lld \n", (long long int)s);
return s;
}
static void Release(LuaSocket* s, int step)
{
if (!s) return;
//printf("Release:%lld \n", (long long int)s);
s->Close();
delete s;
}
static double GetHostByName(const char* host)
{
hostent* hostn = gethostbyname(host);
u_long addr = 0;
if (hostn)
{
addr = *(u_long*)hostn->h_addr_list[0];
}
double d;
memcpy(&d, &addr, sizeof(d));
return d;
}
private:
char* buff_;
};
#endif

View File

@@ -0,0 +1,217 @@
#ifdef _MSC_VER
#include <stdio.h>
#include <stdlib.h>
#include "os_def.h"
#include <_ast.h>
#include <x_thread.h>
#include <x_lock.h>
#include <x_tick.h>
#include <stream.h>
#include <wrand.h>
#include <time.h>
#include <container/vector.h>
#include <x_lock.h>
#include "second_time.h"
//#include <LinkedList.h>
#include "time_stat.h"
static const char s_szLogFileName[] = ("TimeStat.xml");
static const char* s_szTimeProfIndent[] = {
(""), // level_1
(" "), // level_2
(" "), // level_3
(" "), // level_4
(" "), // level_5
(" "), // level_6
(" "), // level_7
(" "), // level_8
(" "), // level_9
(" "), // level_10
(" "), // level_11
(" "), // level_12
(" "), // level_13
(" "), // level_14
(" ") // level_15
};
const char s_szSep[] = ("-------------------------------------------------------------------------------------------\r\n");
const char s_szStartRecordsLabel[] = ("<Records>\r\n");
const char s_szEndRecordsLabel[] = ("</Records>\r\n");
const char s_szStartProfRecord[] = ("<ProfRecord timeSpan=\"");
const char s_szEndProfRecord[] = ("</ProfRecord>\r\n");
const char s_szThreadLabel[] = (" threadId=%d");
const char szXmlEndLable[] = ("\">\r\n");
DWORD TimeProfMgr::s_dwTlsIdx = TLS_OUT_OF_INDEXES;
TimeProfDummy::TimeProfDummy(const char* szUnitName, unsigned int nHashCode)
{
TimeProfMgr& profMgr = *TimeProfMgr::getSingleton().getThreadInst();
TimeProfRecord *pCurRecord = profMgr.getCurrTimeProfRecord();
if (pCurRecord)
{
TimeProfRecord* pChild = pCurRecord->getChildByHash(nHashCode);
if (!pChild)
{
pChild = profMgr.allocRecord();
pChild->reInitBasicData(szUnitName, nHashCode);
pCurRecord->addChild(pChild);
}
pChild->startProf();
profMgr.OnTimeProfRecordStart(pChild);
}
}
TimeProfDummy::~TimeProfDummy()
{
TimeProfMgr& mgr = *TimeProfMgr::getSingleton().getThreadInst();
TimeProfRecord *pCurRecord = mgr.getCurrTimeProfRecord();
pCurRecord->endProf();
mgr.OnTimeProfRecordEnd(pCurRecord);
}
void TimeProfRecord::dump(stream::BaseStream& stream, int level)
{
level = level >= (int)(ArrayCount(s_szTimeProfIndent)) ? (int)(ArrayCount(s_szTimeProfIndent)-1) : level;
stream.write(s_szTimeProfIndent[level], strlen(s_szTimeProfIndent[level])*sizeof(char));
char szData[512] = {0};
float nAvgTime = 0;
if (m_nTotalCount > 0)
nAvgTime = (float)m_nTotalTime / m_nTotalCount;
SNPRINTFA(szData, sizeof(szData), ("<%s ttime=\"%I64u\" tcount=\"%I64u\" atime=\"%f\" maxtime=\"%I64u\" mintime=\"%I64u\" ottime=\"%I64u\" otcount=\"%I64u\" omaxtime=\"%I64u\" omintime=\"%I64u\">\r\n"),
m_szExecUnitName,m_nTotalTime, m_nTotalCount, nAvgTime, m_nMaxTime, m_nMinTime,
m_nOccuTotalTime, m_nOccuTotalCount, m_nOccuMaxTime, m_nOccuMinTime);
stream.write(szData, strlen(szData) * sizeof(szData[0]));
reset();
for (int i = 0; i < m_childrenNode.count(); i++)
m_childrenNode[i]->dump(stream, level+1);
SNPRINTFA(szData, sizeof(szData), ("%s</%s>\r\n"), s_szTimeProfIndent[level], m_szExecUnitName);
stream.write(szData, strlen(szData) * sizeof(szData[0]));
}
void TimeProfRecord::setName(const char* szName)
{
_STRNCPY_A(m_szExecUnitName, szName);
}
TimeProfRecord::TimeProfRecord(const char*, unsigned int)
{
}
TimeProfRecord::~TimeProfRecord(){
clear();
}
void TimeProfRecord::clear()
{
for (int i = 0; i < m_childrenNode.count(); i++)
{
TimeProfRecord *pRecord = m_childrenNode[i];
pRecord->clear();
TimeProfMgr::getSingleton().getThreadInst()->freeRecord(pRecord);
}
m_childrenNode.empty();
}
TimeProfMgr::TimeProfMgr() : m_execUnitRoot("", 0), m_dwThreadId(0)
{
//::timeBeginPeriod(1);
m_execUnitRoot.setName("Root");
m_execUnitRoot.reset(true);
m_execUnitStack.reserve(500);
getCurrentTm(m_lastDumpTime);
m_execUnitStack.push(&m_execUnitRoot);
m_freeRecordList.reserve(500);
allocTimeProfRecord();
}
TimeProfMgr::~TimeProfMgr()
{
//::timeEndPeriod(1);
clear();
}
void TimeProfMgr::getCurrentTm(tm &t)
{
time_t szClock;
time(&szClock);
struct tm *curTime = localtime(&szClock);
t = *curTime;
}
void TimeProfMgr::dumpImpl(stream::BaseStream& stream)
{
dumpDateTimeHeader(stream);
m_execUnitRoot.dump(stream);
stream.write(s_szEndProfRecord, strlen(s_szEndProfRecord)*sizeof(char));
}
void TimeProfMgr::dump()
{
using namespace stream;
FileStream fs(s_szLogFileName, FileStream::faWrite, FileStream::AlwaysOpen, NULL);
int fileSize = fs.getSize();
bool bFirstTime = true;
if (fileSize > (LONGLONG)(strlen(s_szEndProfRecord)*sizeof(char)))
{
bFirstTime = false;
fileSize -= (int)(strlen(s_szEndRecordsLabel)*sizeof(char));
fs.setPosition(fileSize);
}
else
{
fs.setPosition(fileSize);
fs.write(s_szStartRecordsLabel, strlen(s_szStartRecordsLabel)*sizeof(char));
}
for (int i = 0; i < m_vecTimeProfMgr.count(); i++)
{
m_vecTimeProfMgr[i]->dumpImpl(fs);
}
////dumpDateTimeSep(fs);
//dumpDateTimeHeader(fs);
//m_execUnitRoot.dump(fs);
//fs.write(s_szEndProfRecord, strlen(s_szEndProfRecord)*sizeof(char));
////dumpDateTimeSep(fs);
fs.write(s_szEndRecordsLabel, strlen(s_szEndRecordsLabel)*sizeof(char));
}
void TimeProfMgr::dumpDateTimeHeader(stream::BaseStream& stream)
{
char szBeginDateTime[256] = {0};
formatTimeStr(szBeginDateTime, ArrayCount(szBeginDateTime)-1, &m_lastDumpTime);
szBeginDateTime[ArrayCount(szBeginDateTime)-1] = ('\0');
stream.write(s_szStartProfRecord, strlen(s_szStartProfRecord)*sizeof(char));
stream.write(szBeginDateTime, strlen(szBeginDateTime) * sizeof(char));
stream.write("--", 2);
char szDateTime[256] = {0};
getCurrentTm(m_lastDumpTime);
formatTimeStr(szDateTime, ArrayCount(szDateTime)-1, &m_lastDumpTime);
szDateTime[ArrayCount(szDateTime)-1] = ('\0');
stream.write(szDateTime, strlen(szDateTime) * sizeof(char));
// dump thread id
char szThreadInfo[64] = {0};
SNPRINTFA(szThreadInfo, sizeof(szThreadInfo), s_szThreadLabel, m_dwThreadId);
stream.write(szThreadInfo, strlen(szThreadInfo) * sizeof(char));
stream.write(szXmlEndLable, strlen(szXmlEndLable) * sizeof(char));
}
void TimeProfMgr::formatTimeStr(char* szDataBuff, size_t nLen, tm *t)
{
//_tcsftime(szDataBuff, nLen-1, ("%Y-%m-%d_%H:%M:%S"), t);
SNPRINTFA(szDataBuff, (int)(nLen - 1), "%d-%d-%d_%d:%d:%d", t->tm_year + 1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
}
void TimeProfMgr::dumpDateTimeSep(stream::BaseStream& stream)
{
stream.write(s_szSep, strlen(s_szSep) * sizeof(char));
}
#endif

View File

@@ -0,0 +1,295 @@
#ifndef _TIME_STAT_H_
#define _TIME_STAT_H_
#ifdef _MSC_VER
//////////////////////////////////////////////////////////////////////////
// 时间统计分析类
// 功 能:用于追踪程序中调用的函数执行时间消耗情况,定位出性能瓶颈
// 说 明统计按照设定好的时间间隔来输出例如2分钟输出一次将所有函数调用
// 节点信息按照树形结果来呈现(序列化到文件)处理,可以快速的分析出
// 2分钟内每个执行单元消耗了多久时间找出瓶颈所在。
// 例如:在逻辑线程,在逻辑线程每次循环加一个追踪节点,在下面的网络处理、实体管理器、
// 副本管理器等等都增加追踪节点,这样就能详细的跟踪到每个节点耗时占整个耗时的
// 比例。
// 因为逻辑引擎本身采取分时,对每个子(子子)单元都限制了执行时间,这样就对
// 统计分析有影响比如正常情况下实体管理器刷新占据每次例行50%左右的时间,结果
// 因为分时,就算实体刷新出问题,也检测不出来!!!
// 对于此问题,要么是暂时过滤分时;要么是在实体管理器内部设置分时追踪结点。
//////////////////////////////////////////////////////////////////////////
#include <new>
//#include "ObjectCounter.h"
class TimeProfDummy
{
public:
TimeProfDummy(const char* szUnitName, unsigned int nHashCode);
~TimeProfDummy();
};
// 执行时间记录节点
class TimeProfRecord
{
public:
enum
{
MAX_EXEC_UNIT_NAME_LEN = 64, // 最大执行单元名称
};
TimeProfRecord(){}
TimeProfRecord(const char* szUnitName, unsigned int nHashCode);
~TimeProfRecord();
//设置节点名称
void setName(const char* szName);
// 添加一个子执行结点
inline void addChild(TimeProfRecord* record)
{
m_childrenNode.add(record);
}
// 查询节点
//CTimeProfRecord* getChild(const char* szUnitName);
inline TimeProfRecord* getChildByHash(int nHashCode)
{
for (int i = 0; i < m_childrenNode.count(); i++)
{
if ((unsigned int)nHashCode == m_childrenNode[i]->m_nNameHashCode)
return m_childrenNode[i];
}
return NULL;
}
// 输出结点执行时间详细信息
void dump(stream::BaseStream& stream, int level = 0);
// 重置节点数据
inline void reset(bool bIncOccuData = false)
{
m_nTotalCount = 0;
m_nMaxTime = 0;
m_nMinTime = 0;
m_nTotalTime = 0;
if (bIncOccuData)
{
m_nOccuTotalCount = 0;
m_nOccuTotalTime = 0;
m_nOccuMaxTime = 0;
m_nOccuMinTime = 0;
}
}
inline void reInitBasicData(const char* szUnitName, unsigned int nHashCode)
{
ZeroMemory(this, offsetof(TimeProfRecord, m_childrenNode));
_STRNCPY_A(m_szExecUnitName, szUnitName);
for (int i = 0; i < (int)strlen(m_szExecUnitName); i++)
{
if (m_szExecUnitName[i] == ('\"') || m_szExecUnitName[i] == (',') || m_szExecUnitName[i] == ('<')
|| m_szExecUnitName[i] == ('>') || m_szExecUnitName[i] == (':') || m_szExecUnitName[i] == (' '))
m_szExecUnitName[i] = ('_');
}
m_nNameHashCode = nHashCode;
}
inline void startProf()
{
m_nStartTime = _getTickCount();
m_nTotalCount++;
m_nOccuTotalCount++;
}
inline void endProf()
{
m_nEndTime = _getTickCount();
unsigned long long nTimeConsume = m_nEndTime - m_nStartTime;
if (m_nMaxTime < nTimeConsume)
m_nMaxTime = nTimeConsume;
if (m_nMinTime > nTimeConsume)
m_nMinTime = nTimeConsume;
if (m_nOccuMaxTime < nTimeConsume)
m_nOccuMaxTime = nTimeConsume;
if (m_nOccuMinTime > nTimeConsume)
m_nOccuMinTime = nTimeConsume;
m_nTotalTime += nTimeConsume;
m_nOccuTotalTime += nTimeConsume;
}
void clear();
//字符串hash函数需要提供长度
inline static unsigned int hashlstr(const char* str, size_t len)
{
unsigned int h = (unsigned int)len;
size_t step = (len>>5)+1; /* if string is too long, don't hash all its chars */
size_t l1;
for (l1=len; l1>=step; l1-=step) /* compute hash */
h = h ^ ((h<<5)+(h>>2)+(unsigned char)str[l1-1]);
return h;
}
protected:
unsigned int m_nNameHashCode; // 名字Hash码
unsigned long long m_nTotalCount; // 执行次数
unsigned long long m_nOccuTotalCount; // 累积执行次数
unsigned long long m_nMaxTime; // 本次统计最大执行耗时
unsigned long long m_nMinTime; // 本次统计最小执行耗时
unsigned long long m_nOccuMaxTime; // 累积的最大执行耗时
unsigned long long m_nOccuMinTime; // 累积的最小执行耗时
unsigned long long m_nTotalTime; // 整体执行耗时(用于统计平均耗时)
unsigned long long m_nOccuTotalTime; // 累积执行时间
unsigned long long m_nStartTime; // 开始执行时间
unsigned long long m_nEndTime; // 结束执行时间
char m_szExecUnitName[MAX_EXEC_UNIT_NAME_LEN]; // 执行单位名称
container::Vector<TimeProfRecord*> m_childrenNode; // 所有子节点列表
};
// 执行时间管理器
class TimeProfMgr
{
public:
TimeProfMgr();
~TimeProfMgr();
enum
{
ALLOC_RECORD_NUM = 200,
};
bool InitMgr()
{
if (TLS_OUT_OF_INDEXES == s_dwTlsIdx)
{
s_dwTlsIdx = TlsAlloc();
return s_dwTlsIdx != TLS_OUT_OF_INDEXES ? true : false;
}
return false;
}
static TimeProfMgr& getSingleton()
{
static TimeProfMgr mgr;
return mgr;
}
TimeProfMgr* getThreadInst()
{
TimeProfMgr* profMgr = (TimeProfMgr *)TlsGetValue(s_dwTlsIdx);
if (!profMgr)
{
profMgr = new TimeProfMgr();
profMgr->setThreadId(GetCurrentThreadId());
TlsSetValue(s_dwTlsIdx, profMgr);
m_lock.Lock();
m_vecTimeProfMgr.add(profMgr);
m_lock.Unlock();
}
return profMgr;
}
// 开始执行计时
inline void OnTimeProfRecordStart(TimeProfRecord *record)
{
m_execUnitStack.push(record);
}
// 结束执行计时
inline void OnTimeProfRecordEnd(TimeProfRecord *)
{
m_execUnitStack.pop();
}
// 获取当前执行单元结点
inline TimeProfRecord* getCurrTimeProfRecord()
{
int count = m_execUnitStack.count();
if (count > 0)
return m_execUnitStack[count-1];
return NULL;
}
// 输出结点执行时间详细信息
void dump();
inline TimeProfRecord* allocRecord()
{
if (m_freeRecordList.count() <= 0)
allocTimeProfRecord();
return m_freeRecordList.pop();
}
inline void freeRecord(TimeProfRecord *record)
{
m_freeRecordList.add(record);
}
inline void clear()
{
m_execUnitRoot.clear();
for (int i = 0; i < m_freeRecordList.count(); i++)
{
TimeProfRecord *pRecord = m_freeRecordList[i];
if (pRecord)
{
pRecord->~TimeProfRecord();
free(pRecord);
}
}
m_freeRecordList.empty();
m_execUnitStack.empty();
if (s_dwTlsIdx != TLS_OUT_OF_INDEXES)
{
TlsFree(s_dwTlsIdx);
s_dwTlsIdx = TLS_OUT_OF_INDEXES;
}
for (int i = 0; i < m_vecTimeProfMgr.count(); i++)
{
delete m_vecTimeProfMgr[i];
}
m_vecTimeProfMgr.empty();
}
protected:
// 输出时间头
void dumpDateTimeHeader(stream::BaseStream& stream);
// 输出分隔符
void dumpDateTimeSep(stream::BaseStream& stream);
// 获取当前时间
void getCurrentTm(tm &t);
// dump
void dumpImpl(stream::BaseStream& stream);
// 格式化时间
void formatTimeStr(char* szDataBuff, size_t nLen, tm *t);
// 执行一次分配每次分配ALLOC_RECORD_NUM个
inline void allocTimeProfRecord()
{
for (int i = 0; i < ALLOC_RECORD_NUM; i++)
{
TimeProfRecord* pRecords = (TimeProfRecord *)malloc(sizeof(TimeProfRecord));
if (pRecords)
{
new (pRecords)TimeProfRecord();
m_freeRecordList.add(pRecords);
}
}
}
// 设置线程Id
inline void setThreadId(DWORD dwThreadId) { m_dwThreadId = dwThreadId; }
protected:
container::Vector<TimeProfRecord *> m_execUnitStack; // 执行单元结点栈
TimeProfRecord m_execUnitRoot; // 执行单元树的根节点
tm m_lastDumpTime; // 上次dump结束时间
container::Vector<TimeProfRecord*> m_freeRecordList;
static DWORD s_dwTlsIdx; // Tls Slot Index
lock::Mutex m_lock; // Sync for multithread create timeprofmgr object
container::Vector<TimeProfMgr*> m_vecTimeProfMgr; // TimeProfMgr list
DWORD m_dwThreadId; // Current ThreadId
};
#ifdef _TIME_STATE_CHECK_
#define DECLARE_TIME_PROF(name) static unsigned int _STATIC_FUNCTION_HASH_VALUE_= TimeProfRecord::hashlstr(name,strlen(name)); \
TimeProfDummy LocalTimeProfRecord(name, _STATIC_FUNCTION_HASH_VALUE_ );
#define DECLARE_FUN_TIME_PROF() DECLARE_TIME_PROF(__FUNCTION__)
#else
#define DECLARE_TIME_PROF(name_)
#define DECLARE_FUN_TIME_PROF() DECLARE_TIME_PROF(__FUNCTION__)
#endif
#endif
#endif

View File

@@ -0,0 +1,59 @@
#define DEBUG_LOGIC_TIME
#define DEBUG_LOG_INTERVAL 600000
#define DEBUG_LOG_MAX_TIME 500
#ifdef DEBUG_LOGIC_TIME
#define LOGTIME_BEGIN \
static int __LOG_TIME_LOGS[100] = { 0 }; \
int64_t __log_last_t, __log_curr_t; \
__log_curr_t = __log_last_t = _getTickCount(); \
int64_t __log_tick_t; \
int __log_diff_t; \
int __log_idx = 0; \
static int64_t __log_log_t = __log_curr_t + DEBUG_LOG_INTERVAL;
#define LOGTIME \
__log_tick_t = _getTickCount(); \
__log_diff_t = (int)(__log_tick_t - __log_last_t); \
if (__log_idx >= 0 && __log_idx < 100 && __log_diff_t > __LOG_TIME_LOGS[__log_idx]) \
{ \
__LOG_TIME_LOGS[__log_idx] = __log_diff_t; \
} \
__log_last_t = __log_tick_t; \
__log_idx ++;
#define SW_LOGTIME(__log_idx_) \
__log_tick_t = _getTickCount(); \
__log_diff_t = (int)(__log_tick_t - __log_last_t); \
if (__log_idx_ >= 0 && __log_idx_ < 100 && __log_diff_t > __LOG_TIME_LOGS[__log_idx_]) \
{ \
__LOG_TIME_LOGS[__log_idx_] = __log_diff_t; \
} \
__log_idx = __log_idx_;
#define LOGTIME_END(__log_fun, __log_max_time) \
if (__log_curr_t >= __log_log_t && __log_idx >= 0 && __log_idx < 100) \
{ \
bool __log_haslog = true; \
for (int i=0; i<__log_idx; i++) \
{ \
if (__LOG_TIME_LOGS[i] > __log_max_time) \
{ \
if (__log_haslog) { \
OutputMsg(rmError, "=============debug %s time:============", __log_fun); \
__log_haslog = false; \
} \
OutputMsg(rmError, "%d=%d", i, __LOG_TIME_LOGS[i]); \
} \
} \
memset(__LOG_TIME_LOGS, 0, sizeof(__LOG_TIME_LOGS)); \
__log_log_t = __log_curr_t + DEBUG_LOG_INTERVAL; \
}
#else
#define LOGTIME_BEGIN
#define LOGTIME
#define SW_LOGTIME(__log_idx_)
#define LOGTIME_END(__log_fun, __log_max_time)
#endif

View File

@@ -0,0 +1,172 @@
#include <stdlib.h>
#include <stdio.h>
#include "os_def.h"
#include "_ast.h"
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "ltm.h"
}
#include "x_thread.h"
#include "x_tick.h"
#include "x_lock.h"
#include "ref_string.hpp"
#include "stream.h"
#include "share_util.h"
#include "container/str_hash_table.h"
#include "container/queue_list.h"
#include "memory/buffer_allocator.h"
#include "luabase/base_lua.h"
#include "luabase/base_lua_config.h"
#include "luabase/lua_pre_process.h"
#include "luabase/clvariant.h"
#include "luabase/lua_clvariant.h"
#include "luabase/lua_profiler.h"
#include "luabase/script_value.hpp"
#include "luabase/script_value_list.h"
#include "luabase/vsp_def.h"
#include "luabase/base_script.h"
#include "async_worker.h"
AsyncWorker::AsyncWorker(const char* lua_file) : Inherited(),
alloc_("AsyncWorker"), wcb_(NULL), reload_(false)
{
cb_list_.setLock(&cb_list_lock_);
LoadScript(lua_file);
_STRNCPY_A(lua_file_, lua_file);
}
AsyncWorker::~AsyncWorker()
{
cb_list_.flush();
int count = cb_list_.count();
for (int i = 0; i < count; ++i)
{
CBData* cb = cb_list_[i];
if (!cb) continue;
if (cb->params_ && cb->free_func_)
{
cb->free_func_(cb);
}
alloc_.FreeBuffer(cb);
}
cb_list_.clear();
}
int AsyncWorker::Run()
{
if (reload_)
{
reload_ = false;
LoadScript(lua_file_);
}
if (cb_list_.appendCount() <= 0) return 0;
cb_list_.flush();
int count = cb_list_.count();
for (int i = 0; i < count; ++i)
{
CBData* cb = cb_list_[i];
cb->work_func_(cb);
this->wcb_(cb);
}
cb_list_.clear();
return count;
}
void AsyncWorker::OnRoutine()
{
OnStart();
while (!terminated())
{
if (Run() <= 0)
Sleep(1);
}
OnStop();
}
void AsyncWorker::OnStart()
{
OutputMsg(rmError, "AsyncWorker start!");
}
void AsyncWorker::OnStop()
{
OutputMsg(rmError, "AsyncWorker stop!");
}
void AsyncWorker::AppendWork(CBData* cb)
{
cb_list_.append(cb);
}
void AsyncWorker::LoadScript(const char* lua_file)
{
if (lua_file)
{
CVSPDefinition vsp_def;
vsp_def.LoadDefinitions("./data/vspdef.txt");
script_.SetVspDef(&vsp_def);
if (!script_.LoadScript(lua_file))
{
OutputMsg(rmError, "load AsyncWorker script fail!!!file:%s", lua_file);
}
}
}
unsigned int AsyncWorker::SendLuaMessage(ScriptValueList& req, WordFunc func)
{
id_++;
if (id_ == 0) id_++;
CBData* cb = (CBData*)alloc_.AllocBuffer(sizeof(*cb));
new(cb)CBData(this, id_);
cb->worker_ = this;
cb->work_func_ = &AsyncWorker::ExecuteLua;
cb->after_func_ = func;
cb->free_func_ = &AsyncWorker::FreeLuaParams;
cb->params_ = alloc_.AllocBuffer(sizeof(LuaParams));
new(cb->params_)LuaParams();
LuaParams* p = (LuaParams*)cb->params_;
p->req_ = req;
p->result_ << cb->guid_;
AppendWork(cb);
return cb->guid_;
}
void AsyncWorker::FreeLuaParams(void* callback)
{
CBData* cb = (CBData*)callback;
if (cb->params_)
{
((LuaParams*)cb->params_)->~LuaParams();
cb->worker_->GetAlloc().FreeBuffer(cb->params_);
cb->params_ = NULL;
}
}
void AsyncWorker::ExecuteLua(void* cb)
{
CBData* c = (CBData*)cb;
LuaParams* p = (LuaParams*)c->params_;
c->worker_->script_.Call("main", &p->req_, &p->result_);
}

View File

@@ -0,0 +1,93 @@
#ifndef _ASYNC_WORKER_H_
#define _ASYNC_WORKER_H_
/*
* 单独运行的线程,用于非游戏主线程执行的操作
* 比如访问每个web接口。
* 增加新的功能,只需要定义线程的执行函数,以及执行完成后的回调函数
*/
using namespace thread;
using namespace container;
class AsyncWorker: public thread::BaseThread
{
public:
typedef BufferAllocator AsyncWorkerAlloc;
typedef BaseThread Inherited;
typedef void (*WordFunc)(void* cb);
typedef void (*WorkerCallBack)(void* cb);
typedef void (*FreeFunc)(void* cb);
struct LuaParams
{
ScriptValueList req_; // 请求的参数列表
ScriptValueList result_; // 执行完后返回的值
};
struct CBData
{
unsigned int guid_; // 序列号每个执行的函数都会分配一个唯一的id用于回调
WordFunc work_func_; // 在本线程里执行的工作函数比如访问web
WordFunc after_func_; // 在游戏主线程要执行的函数指针,即回调函数
FreeFunc free_func_;
void* params_;
AsyncWorker* worker_;
CBData(AsyncWorker* worker, unsigned int guid):
guid_(guid), work_func_(NULL), after_func_(NULL),
free_func_(NULL), params_(NULL), worker_(worker)
{
}
};
public:
AsyncWorker(const char* lua_file = NULL);
void LoadScript(const char* lua_file);
virtual ~AsyncWorker();
// 新增一个线程执行的操作
void AppendWork(CBData* cb);
public:
AsyncWorkerAlloc& GetAlloc()
{
return alloc_;
}
void SetWorkCallBack(WorkerCallBack wcb)
{
wcb_ = wcb;
}
void Reload()
{
reload_ = true;
}
// 发送执行lua的请求
unsigned int SendLuaMessage(ScriptValueList& req, WordFunc func);
protected:
void OnRoutine();
//单次逻辑处理
int Run();
void OnStart();
void OnStop();
private:
static void FreeLuaParams(void* callback);
static void ExecuteLua(void* cb);
private:
QueueList<CBData*> cb_list_;
Mutex cb_list_lock_;
AsyncWorkerAlloc alloc_;
unsigned int id_;
WorkerCallBack wcb_;
BaseScript script_; // 用于执行lua的代码
bool reload_; // 通知重新加载脚本
char lua_file_[128]; //文件名
};
#endif

View File

@@ -0,0 +1,241 @@
#include <stdio.h>
#include <stdlib.h>
#include "os_def.h"
#include "_ast.h"
#include "share_util.h"
#include "fdop.h"
#ifndef _MSC_VER
#include <sys/stat.h>
#endif
using namespace FDOP;
bool FDOP::FileExists(const char* sFilePath)
{
#ifdef _MSC_VER
DWORD dwAttr = GetFileAttributes(sFilePath);
if (dwAttr == (DWORD) - 1)
return false;
else return true;
#else
if (!access(sFilePath, F_OK))
{
return true;
}
else
{
return false;
}
#endif
}
bool FDOP::DeepCreateDirectory(const char* sDirPath)
{
#ifdef _MSC_VER
char sPath[4096];
LPTSTR sPathPtr = sPath;
size_t dwNameLen, dwBufLen = ArrayCount(sPath) - 1;
DWORD dwAttr;
while (true)
{
dwNameLen = ExtractTopDirectoryName(sDirPath, &sDirPath, sPathPtr, dwBufLen);
//如果目录名称长度超过目录缓冲区长度则放弃
if (dwNameLen >= dwBufLen)
return false;
//如果目录名称长度为0则表示所有目录均已创建完成
if (dwNameLen == 0)
return true;
sPathPtr += dwNameLen;
//如果目录名称不是驱动器名称则检查和创建目录
if (sPathPtr[-1] != ':')
{
//如果目录不存在则创建此目录
dwAttr = GetFileAttributes(sPath);
if ((dwAttr == (DWORD) - 1 && GetLastError() == ERROR_FILE_NOT_FOUND))
{
if (!CreateDirectory(sPath, NULL))
return false;
}
//如果文件存在且文件不是目录则返回false
else if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
{
return false;
}
}
sPathPtr[0] = '\\';
sPathPtr++;
if (dwBufLen > dwNameLen)
dwBufLen -= dwNameLen + 1;
else dwBufLen = 0;
}
return false;
#else
char dirName[256];
_STRNCPY_A(dirName, sDirPath);
int len = strlen(dirName);
if (dirName[len - 1] != '/')
_STRNCAT_A(dirName, "/");
len = strlen(dirName);
for (int i = 1; i < len; i++)
{
if (dirName[i] == '/')
{
dirName[i] = 0;
if (access(dirName, F_OK) != 0)
{
if (mkdir(dirName, 0755) == -1)
{
//OutputMsg(rmError, "mkdir error, %s", dirName);
return false;
}
}
dirName[i] = '/';
}
}
return true;
#endif
}
size_t FDOP::ExtractFileDirectory(const char* sFilePath, char* sDirBuf, size_t dwBufLen)
{
const char* sDirEnd = sFilePath + strlen(sFilePath) - 1;
while (sDirEnd >= sFilePath && *sDirEnd != '/' && *sDirEnd != '\\')
{
sDirEnd--;
}
if (sDirEnd > sFilePath)
{
size_t dwNameLen = sDirEnd - sFilePath;
if (dwBufLen > 0)
{
if (dwBufLen > dwNameLen)
dwBufLen = dwNameLen;
else dwBufLen--;
memcpy(sDirBuf, sFilePath, sizeof(*sDirBuf) * dwBufLen);
sDirBuf[dwBufLen] = 0;
}
return dwNameLen;
}
return 0;
}
size_t FDOP::ExtractTopDirectoryName(const char* sDirPath, const char* *ppChildDirPath, char* sDirName, size_t dwBufLen)
{
const char* sNameEnd;
//跳过目录名称前连续的'/'或'\'
while (*sDirPath && (*sDirPath == '/' || *sDirPath == '\\'))
{
sDirPath++;
}
sNameEnd = sDirPath;
//定位目录名称起始的位置
while (*sNameEnd)
{
if (*sNameEnd == '/' || *sNameEnd == '\\')
break;
sNameEnd++;
}
//拷贝目录名称
if (sNameEnd > sDirPath)
{
size_t dwNameLen = sNameEnd - sDirPath;
if (dwBufLen > 0)
{
if (dwBufLen > dwNameLen)
dwBufLen = dwNameLen;
else dwBufLen--;
memcpy(sDirName, sDirPath, sizeof(*sDirPath) * dwBufLen);
sDirName[dwBufLen] = 0;
if (ppChildDirPath)
*ppChildDirPath = sNameEnd;
}
return dwNameLen;
}
return 0;
}
size_t FDOP::ExtractFileName(const char* sFilePath, char* sNameBuf, size_t dwBufLen)
{
const char* sNameStart;
const char* sNameEnd = sFilePath + strlen(sFilePath) - 1;
//跳过目录名称后连续的'/'或'\'
while (sNameEnd >= sFilePath && (*sNameEnd == '/' || *sNameEnd == '\\'))
{
sNameEnd--;
}
sNameStart = sNameEnd;
sNameEnd++;
//定位目录名称起始的位置
while (sNameStart >= sFilePath)
{
if (*sNameStart == '/' || *sNameStart == '\\')
break;
sNameStart--;
}
sNameStart++;
//拷贝目录名称
if (sNameStart < sNameEnd)
{
size_t dwNameLen = sNameEnd - sNameStart;
if (dwBufLen > 0)
{
if (dwBufLen > dwNameLen)
dwBufLen = dwNameLen;
else dwBufLen--;
memcpy(sNameBuf, sNameStart, sizeof(*sNameStart) * dwBufLen);
sNameBuf[dwBufLen] = 0;
}
return dwNameLen;
}
return 0;
}

View File

@@ -0,0 +1,66 @@
#ifndef _FDOP_H_
#define _FDOP_H_
/************************************************************************
*
* 常用文件与目录操作函数库
*
************************************************************************/
namespace FDOP
{
/* 判断文件或目录是否存在
* 在操作系统中目录也是一个文件如果要判断一个目录是否存在则应当使用DirectoryExists
* 要判断一个文件是否存在且是一个归档文件则应当使用IsArchive。
* @如果文件或目录存在则返回true否则返回false
* %文件路径字符长度不得超过MAX_PATH
*/
bool FileExists(const char* sFilePath);
/* 逐层创建目录
* 如果创建目录C:\a\b\c\d最终目录的父目录不存在则逐级创建父目录并创建最终目录
* @如果目录完全创建成功则函数返回true否则返回false。
* %如果在创建某个父目录成功后并创建子目录失败则函数返回false且已经创建的父目录不会被删除。
* %目录路径的总体字符长度函数要求必须在MAX_PATH个字符长度以内
*/
bool DeepCreateDirectory(const char* sDirPath);
/* 获取文件所在目录路径
* c:\abc\efg\123.txt --> c:\abc\efg\
* c:\abc\efg\ --> c:\abc\
* 参数sDirBuf用于存储目录字符串
* 参数dwBufLen为sDirName参数的缓冲区字符非字节长度其中含需要保留的终止字符
如果dwBufLen值为0则函数不会将目录路径拷贝到sDirBuf中
如果dwBufLen值非0则函数会将目录路径拷贝到sDirBuf中并会在sDirBuf中写入终止符;
如果缓冲区不够则只拷贝dwBufLen-1个字符并会在sDirBuf中写入终止符。
@函数返回拷贝目录路径所需的字符长度(含终止符)
*/
size_t ExtractFileDirectory(const char* sFilePath, char* sDirBuf, size_t dwBufLen);
/* 获取顶层目录名称
* (abc\efg\ --> abc)
* 参数ppChildDirPath用于存顶层目录之后的目录路径参数可以为空
* 参数sDirName用于存储目录字符串
* 参数dwBufLen为sDirName参数的缓冲区字符非字节长度其中含需要保留的终止字符
如果dwBufLen值为0则函数不会将目录名拷贝到sDirName中
如果dwBufLen值非0则函数会将目录名拷贝到sDirName中并会在sDirName中写入终止符;
如果缓冲区不够则只拷贝dwBufLen-1个字符并会在sDirName中写入终止符。
@函数返回拷贝目录名所需的字符长度(含终止符)
*/
size_t ExtractTopDirectoryName(const char* sDirPath, const char* *ppChildDirPath, char* sDirName, size_t dwBufLen);
/* 获取文件或目录名称
* c:\abc\123.txt --> 123.txt
* c:\abc\efg\ --> efg
* 参数sDirBuf用于存储文件名称字符串
* 参数dwBufLen为sNameBuf参数的缓冲区字符非字节长度其中含需要保留的终止字符
如果dwBufLen值为0则函数不会将文件名拷贝到sNameBuf中
如果dwBufLen值非0则函数会将文件名拷贝到sNameBuf中并会在sNameBuf中写入终止符;
如果缓冲区不够则只拷贝dwBufLen-1个字符并会在sNameBuf中写入终止符。
@函数返回拷贝文件名所需的字符长度(含终止符)
*/
size_t ExtractFileName(const char* sFilePath, char* sNameBuf, size_t dwBufLen);
}
#endif

View File

@@ -0,0 +1,36 @@
#pragma once
#include "luabase/base_lua_config.h"
#include "string_ex.h"
/*
ly:使该类可以对外提供读取lua的工具型接口读取lua配置的地方只需要在源文件中引入
本文件而不再是需要在声明中就要引入并继承BaseLuaConfig类
*/
class LuaReader :public BaseLuaConfig
{
typedef BaseLuaConfig Base;
public:
void showError(const char* sError) { OutputMsg(rmError, sError); }
void showTableNotExists(const char* sTableName) { return Base::showTableNotExists(sTableName); }
void showFieldDoesNotContainValue(const char* sFieldName, const char* sValueType) { return Base::showFieldDoesNotContainValue(sFieldName, sValueType); }
bool openGlobalTable(const char* sTableName) { return Base::openGlobalTable(sTableName); }
bool openFieldTable(const char* sTableName) { return Base::openFieldTable(sTableName); }
bool enumTableFirst(){ return Base::enumTableFirst(); }
bool enumTableNext() { return Base::enumTableNext(); }
void endTableEnum() { return Base::endTableEnum(); }
bool getFieldIndexTable(const int IndexStartFromOne) { return Base::getFieldIndexTable(IndexStartFromOne); }
bool fieldTableExists(const char* sTableName) { return Base::feildTableExists(sTableName); }
void closeTable() { return Base::closeTable(); }
const char* getTablePath() { String r; return Base::getTablePath(r); }
const char* getKeyName() { String r; return Base::getKeyName(r); }
inline int getValueType(){ return Base::getValueType(); }
bool getFieldBoolean(const char* sFieldName, const bool* pDefValue = nullptr, int* pIsValid = nullptr) { return Base::getFieldBoolean(sFieldName, pDefValue, pIsValid); }
double getFieldNumber(const char* sFieldName, const double* pDefValue = nullptr, int* pIsValid = nullptr) { return Base::getFieldNumber(sFieldName, pDefValue, pIsValid); }
int64_t getFieldInt64(const char* sFieldName, const int64_t* pDefValue = nullptr, int* pIsValid = nullptr) { return Base::getFieldInt64(sFieldName, pDefValue, pIsValid); }
int getFieldInt(const char* sFieldName, const int* pDefValue = nullptr, int* pIsValid = nullptr) { return Base::getFieldInt(sFieldName, pDefValue, pIsValid); }
const char* getFieldString(const char* sFieldName, const char* pDefValue = nullptr, int* pIsValid = nullptr) { return Base::getFieldString(sFieldName, pDefValue, pIsValid); }
int getFieldStringBuffer(const char* sFieldName, char* sBuffer, size_t dwBufLen) { return Base::getFieldStringBuffer(sFieldName, sBuffer, dwBufLen); }
int getTableLen() { return (int)lua_objlen(lua_, -1); }
};

View File

@@ -0,0 +1,40 @@
#pragma once
template< typename T >
struct Singleton
{
typedef T value_type;
typedef Singleton self_type;
private:// not to be implemented
Singleton(const self_type&){}
self_type& operator = (const self_type&){}
Singleton(){}
friend T;
private:// this struct promises thread safty
struct creator
{
creator()
{ // ensure that instance() called before main() starts
self_type::instance();
}
inline void null_action() const
{
//empty
}
};
static creator creator_;
public:
static value_type& instance()
{ // the object to be returned
static value_type instance_;
// force the initialization of creator_
creator_.null_action();
return instance_;
}
};
template<typename T>
typename Singleton<T>::creator Singleton<T>::creator_;

View File

@@ -0,0 +1,250 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "os_def.h"
#include "_ast.h"
#include "x_tick.h"
#include "x_lock.h"
#include "container/queue_list.h"
#include "share_util.h"
#include "os_def.h"
#include "appitnmsg.h"
#include "server_def.h"
#include "watch_thread.h"
WatchThread::WatchThread()
{
#ifdef _MSC_VER
handle_ = NULL;
#endif
stoped_ = true;
exit_ = true;
msg_list_.setLock(&msg_lock_);
Startup();
}
WatchThread::~WatchThread()
{
Stop();
msg_list_.flush();
msg_list_.clear();
}
void WatchThread::SingleRun()
{
ProcessSysMsg();
//check
time_t now_t = _getTickCount();
for (int i = 0; i < list_.count(); ++i)
{
WatchData& data = list_[i];
if (now_t - data.last_t_ >= data.timeout_)
{
printf("watch thread: %d block!time:%lld current = %d\n",
data.id_, (long long int)(now_t - data.last_t_), list_.count());
if (data.func_)
data.func_(data.params_);
data.last_t_ = now_t; // 避免不断的输出
}
}
}
void WatchThread::PostMsg(UINT uMsg, size_t para1, size_t para2, BlockFunc func, void* params)
{
InterMsg msg;
msg.uMsg = uMsg;
msg.uParam1 = para1;
msg.uParam2 = para2;
msg.func = func;
msg.params = params;
msg_list_.append(msg);
}
void WatchThread::OnRecvSysMsg(UINT msg, size_t p1, size_t p2, BlockFunc func, void* params)
{
switch (msg)
{
case wmAddWatch:
{
int id = (int)p1;
if (Find(id))
{
OutputMsg(rmError, "this id exist:%d", id);
}
WatchData data;
data.id_ = id;
data.last_t_ = _getTickCount();
data.timeout_ = (int)p2;
data.func_ = func;
data.params_ = params;
list_.add(data);
break;
}
case wmReport:
{
WatchData* data = Find((int)p1);
if (data)
{
data->last_t_ = _getTickCount();
}
else
{
printf("%d is not find. report error!!!!\n", (int)p1);
}
break;
}
case wmRemove:
{
int id = (int)p1;
for (int i = 0; i < list_.count(); ++i)
{
WatchData& data = list_[i];
if (data.id_ == id)
{
int count = list_.count();
//查错
//list_.remove(i);
for (int j = i + 1, t = i; j < list_.count(); j++, t++)
{
WatchData& srcData = list_[j];
WatchData& destData = list_[t];
memcpy(&destData, &srcData, sizeof(WatchData));
}
list_.trunc(count-1);
return;
}
}
break;
}
default:
break;
}
}
void WatchThread::ProcessSysMsg()
{
msg_list_.flush();
int count = msg_list_.count();
for (int i = 0; i < count; ++i)
{
InterMsg& msg = msg_list_[i];
OnRecvSysMsg(msg.uMsg, msg.uParam1, msg.uParam2, msg.func, msg.params);
}
msg_list_.clear();
}
void WatchThread::OnWorkThreadStart()
{
OutputMsg(rmError, "watch thread start");
}
void WatchThread::OnWorkThreadStop()
{
OutputMsg(rmError, "watch thread stop");
}
#ifdef _MSC_VER
void STDCALL WatchThread::Work_R(WatchThread* ptr)
#else
void* WatchThread::Work_R(void* ptr)
#endif
{
WatchThread* watch = (WatchThread*)ptr;
watch->OnWorkThreadStart();
while (!watch->stoped_)
{
watch->SingleRun();
Sleep(1);
}
watch->OnWorkThreadStop();
watch->exit_ = true;
#ifdef _MSC_VER
ExitThread(0);//设置线程退出返回值
#else
return NULL;
#endif
}
bool WatchThread::Startup()
{
bool ret = true;
int err = 0;
stoped_ = false;
#ifdef _MSC_VER
handle_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Work_R, this, 0, &thread_id_);
if (!handle_)
{
err = GetLastError();
ret = false;
}
#else
if (pthread_create(&thread_id_, NULL, Work_R, this))
{
err = errno;
ret = false;
}
#endif
if (!ret)
{
OutputError(err, ("创建监控线程失败"));
return false;
}
exit_ = false;
return true;
}
void WatchThread::Stop()
{
stoped_ = true;
while (!exit_)
{
Sleep(10);
}
#ifdef _MSC_VER
CloseThread(handle_);
#endif
}
WatchThread::WatchData* WatchThread::Find(int id)
{
for (int i = 0; i < list_.count(); ++i)
{
WatchData& data = list_[i];
if (data.id_ == id)
{
return &data;
}
}
return NULL;
}

View File

@@ -0,0 +1,102 @@
#ifndef _WATCH_THREAD_H_
#define _WATCH_THREAD_H_
using namespace tick64;
using namespace container;
using namespace lock;
typedef void (*BlockFunc)(void*);
class WatchThread
{
// 可以考虑加个超时处理,外部传个函数指针进来
struct WatchData
{
int id_;
int64_t last_t_;
int timeout_;
BlockFunc func_;
void* params_;
WatchData() : id_(0), last_t_(0), timeout_(0), func_(NULL), params_(NULL)
{
}
};
enum WatchMsg
{
wmAddWatch,
wmReport,
wmRemove,
};
typedef struct
{
unsigned int uMsg; //消息号
size_t uParam1;//消息参数1
size_t uParam2;//消息参数2
BlockFunc func;
void* params;
}InterMsg;
public:
WatchThread();
virtual ~WatchThread();
bool Startup();
void Stop();
#ifdef _MSC_VER
unsigned long GetThreadId()
#else
pthread_t GetThreadId()
#endif
{
return thread_id_;
}
void AddWatch(int id, int timeout, BlockFunc func = NULL, void* params = NULL)
{
PostMsg(wmAddWatch, id, timeout, func, params);
}
void RemoveWatch(int id)
{
PostMsg(wmRemove, id, 0, NULL, NULL);
}
void Report(int id)
{
PostMsg(wmReport, id, 0, NULL, NULL);
}
protected:
virtual void OnWorkThreadStart();
virtual void OnWorkThreadStop();
protected:
void SingleRun();
void ProcessSysMsg();
void OnRecvSysMsg(UINT msg, size_t p1, size_t p2, BlockFunc func, void* params);
void PostMsg(UINT uMsg, size_t para1, size_t para2, BlockFunc func, void* params);
WatchData* Find(int id);
private:
#ifdef _MSC_VER
static void STDCALL Work_R(WatchThread* ptr);
#else
static void* Work_R(void* ptr);
#endif
private:
#ifdef _MSC_VER
HANDLE handle_; //工作线程句柄
unsigned long thread_id_; //线程ID
#else
pthread_t thread_id_;
#endif
bool stoped_; //是否标记为停止
bool exit_;
QueueList<InterMsg> msg_list_; //内部消息列表
Mutex msg_lock_; //内部消息列表锁
Vector<WatchData> list_;
};
#endif

BIN
Gateway/gateway/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,62 @@
cmake_minimum_required (VERSION 2.8.12.2)
#项目名
project (gate)
#cmake_policy(SET CMP0015 OLD)
#头文件
include_directories(
./
)
# 源文件及头文件
file(GLOB_RECURSE Gate_CODELIST "${PROJECT_SOURCE_DIR}/*.cc" "${PROJECT_SOURCE_DIR}/*.h")
# 代码分组
#group_by_dir(${PROJECT_SOURCE_DIR}/gateway ${Gate_CODELIST})
#链接库
link_directories( ${Libs_Dir} )
if(MSVC)
set(GAME_LIBRARIES
ws2_32
srv
Mswsock
Dbghelp
Winmm
libmysql
mysqlclient
common
)
else()
set(GAME_LIBRARIES
rt
pthread
mysqlclient
#lua
srv
common
)
endif(MSVC)
# Gate输出目录
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/../../Exec/Gateway)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/../../Exec/Gateway)
if ( ${CMAKE_BUILD_TYPE} STREQUAL "Release" )
set( _DEBUG 0 )
else ()
set( _DEBUG 1 )
endif()
if ( _DEBUG )
set( EXE_NAME gateway_d )
else()
set( EXE_NAME gateway_r )
endif()
add_executable(${EXE_NAME} ${Gate_CODELIST})
add_dependencies(${EXE_NAME} common)
target_link_libraries(${EXE_NAME} ${GAME_LIBRARIES})

View File

@@ -0,0 +1,2 @@
#include "StdAfx.h"

81
Gateway/gateway/StdAfx.h Normal file
View File

@@ -0,0 +1,81 @@
#define USE_EPOLL false
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "os_def.h"
#include <_ast.h>
#ifndef _MSC_VER
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include <x_thread.h>
#include <net/base_socket.h>
#include <x_lock.h>
#include <x_tick.h>
#include <container/queue_list.h>
#include "share_util.h"
#include "memory/buffer_allocator.h"
#include "memory/memory_container.hpp"
#include "appitnmsg.h"
#include "data_packet.hpp"
#include "data_packet_reader.hpp"
#include "net/send_packet_pool.h"
#include "net/work_socket.h"
#include "net/net_client.h"
#include "net/server_socket.h"
#include "server_def.h"
#include "gate/gate_proto.h"
#include <stream.h>
#ifdef _MSC_VER
#include "statistic/time_stat.h"
#endif
#include "encrypt/CRC.h"
#include "encrypt/Encrypt.h"
#include "flog/file_logger.h"
#include "second_time.h"
#include "container/static_hash_table.h"
#include <ref_class.hpp>
#include <ref_string.hpp>
#include <time.h>
#include "encrypt/EDPass.h"
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include "luabase/base_lua.h"
#include "luabase/base_lua_config.h"
#include "luabase/script_value.hpp"
#include "luabase/script_value_list.h"
#include "luabase/lua_pre_process.h"
#include "luabase/vsp_def.h"
#include "luabase/base_script.h"
#include "utils/fdop.h"
#include "gate_def.h"
#include "srv/socket_srv.h"
#include "gate_server.h"
#include "config/ws_gate_config.h"
#include "client/client.h"
#include "srv/game_client_mgr.h"
#include "gameworld/game_world_client.h"

View File

@@ -0,0 +1,590 @@
/*
* sha1.cpp
*
* Copyright (C) 1998, 2009
* Paul E. Jones <paulej@packetizer.com>
* All Rights Reserved.
*
*****************************************************************************
* $Id: sha1.cpp 12 2009-06-22 19:34:25Z paulej $
*****************************************************************************
*
* Description:
* This class implements the Secure Hashing Standard as defined
* in FIPS PUB 180-1 published April 17, 1995.
*
* The Secure Hashing Standard, which uses the Secure Hashing
* Algorithm (SHA), produces a 160-bit message digest for a
* given data stream. In theory, it is highly improbable that
* two messages will produce the same message digest. Therefore,
* this algorithm can serve as a means of providing a "fingerprint"
* for a message.
*
* Portability Issues:
* SHA-1 is defined in terms of 32-bit "words". This code was
* written with the expectation that the processor has at least
* a 32-bit machine word size. If the machine word size is larger,
* the code should still function properly. One caveat to that
* is that the input functions taking characters and character arrays
* assume that only 8 bits of information are stored in each character.
*
* Caveats:
* SHA-1 is designed to work with messages less than 2^64 bits long.
* Although SHA-1 allows a message digest to be generated for
* messages of any number of bits less than 2^64, this implementation
* only works with messages with a length that is a multiple of 8
* bits.
*
*/
#include "sha1.h"
/*
* SHA1
*
* Description:
* This is the constructor for the sha1 class.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
SHA1::SHA1()
{
Reset();
}
/*
* ~SHA1
*
* Description:
* This is the destructor for the sha1 class
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
SHA1::~SHA1()
{
// The destructor does nothing
}
/*
* Reset
*
* Description:
* This function will initialize the sha1 class member variables
* in preparation for computing a new message digest.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Reset()
{
Length_Low = 0;
Length_High = 0;
Message_Block_Index = 0;
H[0] = 0x67452301;
H[1] = 0xEFCDAB89;
H[2] = 0x98BADCFE;
H[3] = 0x10325476;
H[4] = 0xC3D2E1F0;
Computed = false;
Corrupted = false;
}
/*
* Result
*
* Description:
* This function will return the 160-bit message digest into the
* array provided.
*
* Parameters:
* message_digest_array: [out]
* This is an array of five unsigned integers which will be filled
* with the message digest that has been computed.
*
* Returns:
* True if successful, false if it failed.
*
* Comments:
*
*/
bool SHA1::Result(unsigned *message_digest_array)
{
int i; // Counter
if (Corrupted)
{
return false;
}
if (!Computed)
{
PadMessage();
Computed = true;
}
for(i = 0; i < 5; i++)
{
message_digest_array[i] = H[i];
}
return true;
}
/*
* Input
*
* Description:
* This function accepts an array of octets as the next portion of
* the message.
*
* Parameters:
* message_array: [in]
* An array of characters representing the next portion of the
* message.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Input( const unsigned char *message_array,
unsigned length)
{
if (!length)
{
return;
}
if (Computed || Corrupted)
{
Corrupted = true;
return;
}
while(length-- && !Corrupted)
{
Message_Block[Message_Block_Index++] = (*message_array & 0xFF);
Length_Low += 8;
Length_Low &= 0xFFFFFFFF; // Force it to 32 bits
if (Length_Low == 0)
{
Length_High++;
Length_High &= 0xFFFFFFFF; // Force it to 32 bits
if (Length_High == 0)
{
Corrupted = true; // Message is too long
}
}
if (Message_Block_Index == 64)
{
ProcessMessageBlock();
}
message_array++;
}
}
/*
* Input
*
* Description:
* This function accepts an array of octets as the next portion of
* the message.
*
* Parameters:
* message_array: [in]
* An array of characters representing the next portion of the
* message.
* length: [in]
* The length of the message_array
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Input( const char *message_array,
unsigned length)
{
Input((unsigned char *) message_array, length);
}
/*
* Input
*
* Description:
* This function accepts a single octets as the next message element.
*
* Parameters:
* message_element: [in]
* The next octet in the message.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Input(unsigned char message_element)
{
Input(&message_element, 1);
}
/*
* Input
*
* Description:
* This function accepts a single octet as the next message element.
*
* Parameters:
* message_element: [in]
* The next octet in the message.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Input(char message_element)
{
Input((unsigned char *) &message_element, 1);
}
/*
* operator<<
*
* Description:
* This operator makes it convenient to provide character strings to
* the SHA1 object for processing.
*
* Parameters:
* message_array: [in]
* The character array to take as input.
*
* Returns:
* A reference to the SHA1 object.
*
* Comments:
* Each character is assumed to hold 8 bits of information.
*
*/
SHA1& SHA1::operator<<(const char *message_array)
{
const char *p = message_array;
while(*p)
{
Input(*p);
p++;
}
return *this;
}
/*
* operator<<
*
* Description:
* This operator makes it convenient to provide character strings to
* the SHA1 object for processing.
*
* Parameters:
* message_array: [in]
* The character array to take as input.
*
* Returns:
* A reference to the SHA1 object.
*
* Comments:
* Each character is assumed to hold 8 bits of information.
*
*/
SHA1& SHA1::operator<<(const unsigned char *message_array)
{
const unsigned char *p = message_array;
while(*p)
{
Input(*p);
p++;
}
return *this;
}
/*
* operator<<
*
* Description:
* This function provides the next octet in the message.
*
* Parameters:
* message_element: [in]
* The next octet in the message
*
* Returns:
* A reference to the SHA1 object.
*
* Comments:
* The character is assumed to hold 8 bits of information.
*
*/
SHA1& SHA1::operator<<(const char message_element)
{
Input((unsigned char *) &message_element, 1);
return *this;
}
/*
* operator<<
*
* Description:
* This function provides the next octet in the message.
*
* Parameters:
* message_element: [in]
* The next octet in the message
*
* Returns:
* A reference to the SHA1 object.
*
* Comments:
* The character is assumed to hold 8 bits of information.
*
*/
SHA1& SHA1::operator<<(const unsigned char message_element)
{
Input(&message_element, 1);
return *this;
}
/*
* ProcessMessageBlock
*
* Description:
* This function will process the next 512 bits of the message
* stored in the Message_Block array.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
* Many of the variable names in this function, especially the single
* character names, were used because those were the names used
* in the publication.
*
*/
void SHA1::ProcessMessageBlock()
{
const unsigned K[] = { // Constants defined for SHA-1
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t; // Loop counter
unsigned temp; // Temporary word value
unsigned W[80]; // Word sequence
unsigned A, B, C, D, E; // Word buffers
/*
* Initialize the first 16 words in the array W
*/
for(t = 0; t < 16; t++)
{
W[t] = ((unsigned) Message_Block[t * 4]) << 24;
W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
}
for(t = 16; t < 80; t++)
{
W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = H[0];
B = H[1];
C = H[2];
D = H[3];
E = H[4];
for(t = 0; t < 20; t++)
{
temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for(t = 20; t < 40; t++)
{
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for(t = 40; t < 60; t++)
{
temp = CircularShift(5,A) +
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for(t = 60; t < 80; t++)
{
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
H[0] = (H[0] + A) & 0xFFFFFFFF;
H[1] = (H[1] + B) & 0xFFFFFFFF;
H[2] = (H[2] + C) & 0xFFFFFFFF;
H[3] = (H[3] + D) & 0xFFFFFFFF;
H[4] = (H[4] + E) & 0xFFFFFFFF;
Message_Block_Index = 0;
}
/*
* PadMessage
*
* Description:
* According to the standard, the message must be padded to an even
* 512 bits. The first padding bit must be a '1'. The last 64 bits
* represent the length of the original message. All bits in between
* should be 0. This function will pad the message according to those
* rules by filling the message_block array accordingly. It will also
* call ProcessMessageBlock() appropriately. When it returns, it
* can be assumed that the message digest has been computed.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::PadMessage()
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second block.
*/
if (Message_Block_Index > 55)
{
Message_Block[Message_Block_Index++] = 0x80;
while(Message_Block_Index < 64)
{
Message_Block[Message_Block_Index++] = 0;
}
ProcessMessageBlock();
while(Message_Block_Index < 56)
{
Message_Block[Message_Block_Index++] = 0;
}
}
else
{
Message_Block[Message_Block_Index++] = 0x80;
while(Message_Block_Index < 56)
{
Message_Block[Message_Block_Index++] = 0;
}
}
/*
* Store the message length as the last 8 octets
*/
Message_Block[56] = (Length_High >> 24) & 0xFF;
Message_Block[57] = (Length_High >> 16) & 0xFF;
Message_Block[58] = (Length_High >> 8) & 0xFF;
Message_Block[59] = (Length_High) & 0xFF;
Message_Block[60] = (Length_Low >> 24) & 0xFF;
Message_Block[61] = (Length_Low >> 16) & 0xFF;
Message_Block[62] = (Length_Low >> 8) & 0xFF;
Message_Block[63] = (Length_Low) & 0xFF;
ProcessMessageBlock();
}
/*
* CircularShift
*
* Description:
* This member function will perform a circular shifting operation.
*
* Parameters:
* bits: [in]
* The number of bits to shift (1-31)
* word: [in]
* The value to shift (assumes a 32-bit integer)
*
* Returns:
* The shifted value.
*
* Comments:
*
*/
unsigned SHA1::CircularShift(int bits, unsigned word)
{
return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
}

View File

@@ -0,0 +1,90 @@
/*
* sha1.h
*
* Copyright (C) 1998, 2009
* Paul E. Jones <paulej@packetizer.com>
* All Rights Reserved.
*
*****************************************************************************
* $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $
*****************************************************************************
*
* Description:
* This class implements the Secure Hashing Standard as defined
* in FIPS PUB 180-1 published April 17, 1995.
*
* Many of the variable names in this class, especially the single
* character names, were used because those were the names used
* in the publication.
*
* Please read the file sha1.cpp for more information.
*
*/
#ifndef _SHA1_H_
#define _SHA1_H_
class SHA1
{
public:
SHA1();
virtual ~SHA1();
/*
* Re-initialize the class
*/
void Reset();
/*
* Returns the message digest
*/
bool Result(unsigned *message_digest_array);
/*
* Provide input to SHA1
*/
void Input( const unsigned char *message_array,
unsigned length);
void Input( const char *message_array,
unsigned length);
void Input(unsigned char message_element);
void Input(char message_element);
SHA1& operator<<(const char *message_array);
SHA1& operator<<(const unsigned char *message_array);
SHA1& operator<<(const char message_element);
SHA1& operator<<(const unsigned char message_element);
private:
/*
* Process the next 512 bits of the message
*/
void ProcessMessageBlock();
/*
* Pads the current message block to 512 bits
*/
void PadMessage();
/*
* Performs a circular left shift operation
*/
inline unsigned CircularShift(int bits, unsigned word);
unsigned H[5]; // Message digest buffers
unsigned Length_Low; // Message length in bits
unsigned Length_High; // Message length in bits
unsigned char Message_Block[64]; // 512-bit message blocks
int Message_Block_Index; // Index into message block array
bool Computed; // Is the digest computed?
bool Corrupted; // Is the message digest corruped?
};
#endif // _SHA1_H_

8
Gateway/gateway/build.sh Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
cd $(cd "$(dirname "$0")" && pwd)
srcDIR=`pwd`
cd $srcDIR/build
cmake ..
make -j2

View File

@@ -0,0 +1,399 @@
#include "StdAfx.h"
#include "client.h"
#include "base/sha1.h"
#include "base64.h"
BaseAllocator Client::alloc("ClientAlloc");
Client::Client(GameClientMgr *cli_mgr, SOCKET s, sockaddr_in* addr) {
shake_hands_ = false;
fd_ = s;
cli_mgr_ = cli_mgr;
send_packet_ = new DataPacket(&alloc);
send_packet_->reserve(SEND_PACKET_MAX);
send_packet_->setLength(0);
memcpy(&remote_addr_, addr, sizeof(sockaddr_in));
net_id_.socket_ = s;
conn_status_ = ConnStatusDef::CS_CONNED;
skey_ = 0;
is_close_ = false;
real_ip[0] = 0;
}
Client ::~Client() {
for (auto it : recv_list_) {
SafeDelete(it);
}
SafeDelete(send_packet_);
recv_list_.clear();
for (auto it : gw_recv_list_) {
SafeDelete(it);
}
real_ip[0] = 0;
}
int Client::SetBlockMode(const bool block) {
unsigned long flag = block ? 0 : 1;
#ifdef _MSC_VER
return ioctlsocket(fd_, FIONBIO, &flag);
#else
return ioctl(fd_, FIONBIO, &flag);//改为非阻塞;
#endif
}
void Client::RecvData(void) {
if (is_close_) return;
static char buf[1024];
while (true) {
int buflen = recv(fd_, buf, sizeof(buf), 0);
if (buflen < 0) {
// 由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可读
// 在这里就当作是该次事件已处理
#ifdef _MSC_VER
if (WSAGetLastError() == WSAECONNABORTED) {
Close();
return;
} else if (WSAGetLastError() == WSAEWOULDBLOCK) {
#else
if (WSAGetLastError() == EINPROGRESS || WSAGetLastError() == EAGAIN) {
#endif
break;
} else {
MSG_ERR("not handle errno:[%d]%s", WSAGetLastError(), strerror(WSAGetLastError()));
Close();
return;
}
} else if (buflen == 0) {
// 这里表示对端的socket已正常关闭.
Close();
return;
}
if (shake_hands_) {
DataPacket* dp = new DataPacket(&alloc);
dp->writeBuf(buf, buflen);
dp->setPosition(0);
recv_list_.push_back(dp);
} else {
//进行websocket握手
ShakeHandsHandle(buf, buflen);
return;
}
}
}
bool Client::SendData(void) {
size_t splen = send_packet_->getAvaliableLength();
if (splen <= 0) { return true; }
int lsed = send(fd_, send_packet_->getOffsetPtr(), (int)splen, 0);
if(lsed <= 0) { return true; }
if (lsed < splen) {
send_packet_->setPosition(send_packet_->getPosition() + lsed);
return false;
} else {
send_packet_->setLength(0);
}
return true;
}
void Client::WriteEvent(void) {
if (is_close_) return;
DataPacket* dp = NULL;
while (true) {
if (gw_recv_list_.empty()) { break; }
dp = *(gw_recv_list_.begin());
gw_recv_list_.pop_front();
FlushWsPack(dp->getOffsetPtr(), dp->getAvaliableLength());
SafeDelete(dp);
}
if(send_packet_->getAvaliableLength() > 0) {
cli_mgr_->HaveData(this);
}
}
void Client::Flush(const char *buf, size_t len) {
if (send_packet_->getAvaliableLength() + len > SEND_PACKET_MAX) {
MSG_ERR("send packet is max, fd:%d", fd_);
Close();
return;
} else {
size_t pos = send_packet_->getPosition();
send_packet_->setPosition(pos + send_packet_->getAvaliableLength());
send_packet_->writeBuf(buf, len);
send_packet_->setPosition(pos);
}
}
void Client::SendNewSession(void) {
static GameWorldClient* wgc = cli_mgr_->GetGameWorldClient();
DataPacket &dp = wgc->AllocProtoPacket(GM_OPEN,net_id_.socket_,net_id_.index_,net_id_.gate_id_);
if (real_ip[0] != 0)
dp.writeBuf(real_ip, 32);
else
dp.writeBuf(inet_ntoa(remote_addr_.sin_addr), 32);
wgc->flushProtoPacket(dp);
OutputMsg(rmTip, _T("[Login] (2) 握手成功通知LogicServer创建一个玩家Gate gatekey(%d)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),
skey_, net_id_.socket_, net_id_.index_, net_id_.gate_id_, GetCurrentThreadId());
}
void Client::SendSessionClose(void) {
static GameWorldClient* wgc = cli_mgr_->GetGameWorldClient();
DataPacket &dp = wgc->AllocProtoPacket(GM_CLOSE,net_id_.socket_,net_id_.index_,net_id_.gate_id_);
wgc->flushProtoPacket(dp);
}
void Client::Close(void) {
MSG_ERR("close client, fd:%d,index:%d", net_id_.socket_, net_id_.index_);
cli_mgr_->CloseClient(this);
SendSessionClose();
is_close_ = true;
}
#define WEB_SOCKET_HANDS_RE "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\n\r\n"
#define MAGIC_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
void Client::ShakeHandsHandle(const char* buf, int buflen) {
char key[512]; memset(key, 0, 512);
for (int i = 0; i < buflen; ++i)
{
if (FindHttpParam("Sec-WebSocket-Key", buf+i)) {
short k = i + 17, ki = 0;
while(*(buf + k) != '\r' && *(buf + k) != '\n' && *(buf + k) != '\0') {
if (*(buf + k) == ':' || *(buf + k) == ' '){
++k; continue;
} else {
key[ki++] = *(buf + k);
}
++k;
}
break;
}
}
memset(real_ip, 0, sizeof(real_ip));
for (int i = 0; i < buflen; ++i)
{
if (FindHttpParam("X-Real-IP", buf+i)) {
short k = i + 9, ki = 0;
while(*(buf + k) != '\r' && *(buf + k) != '\n' && *(buf + k) != '\0') {
if (*(buf + k) == ':' || *(buf + k) == ' '){
++k; continue;
} else {
real_ip[ki++] = *(buf + k);
}
++k;
}
break;
}
}
//MSG_LOG("key:%s...", key);
memcpy(key + strlen(key), MAGIC_KEY, sizeof(MAGIC_KEY));
//MSG_LOG("megerkey:%s...", key);
//求哈希1
SHA1 sha;
unsigned int message_digest[5];
sha.Reset();
sha << key;
sha.Result(message_digest);
for (int i = 0; i < 5; i++) {
message_digest[i] = htonl(message_digest[i]);
}
memset(key, 0, 512);
base64_encode(key, reinterpret_cast<const char*>(message_digest), 20);
char http_res[512] = "";
sprintf(http_res, WEB_SOCKET_HANDS_RE, key);
Flush(http_res, strlen(http_res));
//MSG_LOG("res:%s...",http_res);//fkYTdNEVkParesYkrM4S
SendData();
shake_hands_ = true;
SendNewSession();//发送到gameworld新增连接
}
void Client::PacketHandle(void) {
if (is_close_) return;
while (!recv_list_.empty()) {
auto dpit = recv_list_.begin();
DataPacket* dp = *dpit;
//读取websocket固定包头
if (!ws_head_.rh) {
//这个包不够一个头部的大小
if (dp->getAvaliableLength() < 2) {
if (MergePacketList(dpit)) continue;
else break;
}
//读取
uint8_t head = 0;
dp->readBuf(&head, 1);
ws_head_.fin = head >> 7;
ws_head_.opcode = head & 0xF;
dp->readBuf(&head, 1);
ws_head_.len = head & 0x7F;
ws_head_.mask = head >> 7;
ws_head_.rh = 1;//标记头部读取完成
}
//读取长度
if (!ws_head_.rl) {
uint8_t nsize = ws_head_.GetLenNeedByte();
if (nsize) {
//这个包不够一个长度
if (dp->getAvaliableLength() < nsize) {
if (MergePacketList(dpit)) continue;
else break;
}
if (nsize == 2) {
(*dp) >> ws_head_.ex_len.v16;
ws_head_.ex_len.v16 = ntohs(ws_head_.ex_len.v16);
} else {
(*dp) >> ws_head_.ex_len.v32;
ws_head_.ex_len.v32 = ntohl((u_long)ws_head_.ex_len.v32);
}
}
ws_head_.rl = 1;
}
//读取MKEY
if (!ws_head_.rk) {
if (ws_head_.mask) {
//这个包不够一个key
if (dp->getAvaliableLength() < 4) {
if (MergePacketList(dpit)) continue;
else break;
}
(*dp) >> ws_head_.mkey[0];
(*dp) >> ws_head_.mkey[1];
(*dp) >> ws_head_.mkey[2];
(*dp) >> ws_head_.mkey[3];
}
ws_head_.rk = 1;
}
//读取数据段
uint64_t data_len = ws_head_.GetLen();
if (dp->getAvaliableLength() < data_len) {
if (MergePacketList(dpit)) continue;
else break;
}
if (ws_head_.mask) {
char* dptr = dp->getOffsetPtr();
for (size_t i = 0; i < data_len; ++i) {
dptr[i] = dptr[i] ^ ws_head_.mkey[i % 4];
}
}
if (!OnRecv(dp->getOffsetPtr(), data_len)) {
return;
}
ws_head_.reset();
dp->adjustOffset(data_len);
//这个包读取完了
if (dp->getAvaliableLength() <= 0) {
recv_list_.pop_front();
SafeDelete(dp);
}
}
}
bool Client::OnRecv(const char* buf, size_t size) {
if (conn_status_ == CS_COMMUNICATE) {
if (ws_head_.opcode == OPCODE_CLR) {
Close();
return false;
}
if (size < 4 + 2) {
MSG_ERR("size is min");
return true;
}
//截去key
unsigned short tag = *((unsigned short*)buf);
if (tag != skey_) {
Close();
return false;
}
char* pdata = (char*)buf + sizeof(unsigned short);
size -= 2;
//截去验证
uint32_t check = *((uint32_t*)pdata);
pdata = pdata + sizeof(uint32_t);
size -= 4;
//发送给游戏服
static GameWorldClient* wgc = cli_mgr_->GetGameWorldClient();
DataPacket &pack = wgc->AllocProtoPacket(GM_DATA,net_id_.socket_,net_id_.index_,net_id_.gate_id_);
#ifdef _DEBUG
const unsigned char* proto = pdata;
OutputMsg(rmTip, "<[sock:%d,idx:%d] Recv(%d,%d)", fd_, GetSessionId(), *proto, *(proto+1));
#endif
pack.writeBuf(pdata, size);
wgc->flushProtoPacket(pack);
//MSG_ERR("size is [%d + 4 + 2]", size);
return true;
}
if (conn_status_ == CS_CONNED) { //刚连接上来
uint32_t tag = *((uint32_t*)buf);
if (tag != DEFAULT_TAG) {
Close();
return false;
}
skey_ = wrand(SHRT_MAX);
FlushWsPack((char *)&skey_, 2);
SendData();
conn_status_ = CS_COMMUNICATE;
}
return true;
}
void Client::FlushWsPack(const char* buf, size_t size) {
static DataPacket pack(&alloc);
pack.setLength(0);
pack << (uint8_t)0x82;//写头部
//写长度
if (size >= 126) {//7位放不下
if (size <= 0xFFFF) {//16位放
pack << (uint8_t)126;
pack << (uint16_t)htons((u_short)size);
} else {//64位放
pack << (uint8_t)127;
pack << (uint64_t)OrderSwap64(size);
}
} else {
pack << (uint8_t)size;
}
//写数据
pack.writeBuf(buf, size);
pack.setPosition(0);
Flush(pack.getOffsetPtr(), pack.getAvaliableLength());
}
void Client::OnGameWorldRecv(const char* buf, size_t size) {
DataPacket *dp = new DataPacket(&alloc);
(*dp) << (uint16_t)skey_;
#ifdef _DEBUG
const unsigned char* proto = buf;
OutputMsg(rmTip, ">[sock:%d,idx:%d] Send(%d,%d)", fd_, GetSessionId(), *proto, *(proto+1));
#endif
dp->writeBuf(buf, size);
dp->setPosition(0);
gw_recv_list_.push_back(dp);
}
bool Client::MergePacketList(std::list<DataPacket*>::iterator &dpit) {
auto sdpit = dpit++;
if (dpit == recv_list_.end()) return false;
DataPacket* sdp = *sdpit;
//合并第二个到第一个
sdp->writeBuf((*dpit)->getOffsetPtr(), (*dpit)->getAvaliableLength());
SafeDelete((*dpit));
recv_list_.erase(dpit);
return true;
}
bool Client::FindHttpParam(const char * param, const char * buf) {
while (*param == *buf) {
if (*(param + 1) == '\0') return true;
++param; ++buf;
}
return false;
}

View File

@@ -0,0 +1,106 @@
#pragma once
#include <list>
#define SEND_PACKET_MAX 1024*1024*8
#define DEFAULT_TAG 0xCA0FFFFF
enum WebSocketOpcode { //操作码定义类型
OPCODE_MID = 0x0,//标识一个中间数据包
OPCODE_TXT = 0x1,//标识一个text类型数据包
OPCODE_BIN = 0x2,//标识一个binary类型数据包
//0x3 - 7保留
OPCODE_CLR = 0x8,//标识一个断开连接类型数据包
OPCODE_PIN = 0x9,//标识一个ping类型数据包
OPCODE_PON = 0xA,//表示一个pong类型数据包
};
#pragma pack(push,1)
struct WebSocketHead {
uint8_t fin : 1;//标识是否为此消息的最后一个数据包
uint8_t rsv1 : 1;//保留位1
uint8_t rsv2 : 1;//保留位2
uint8_t rsv3 : 1;//保留位3
uint8_t opcode : 4;//操作码
uint8_t mask : 1; //是否需要掩码
uint8_t len : 7;//长度
union {
uint16_t v16;//长度为126时
uint32_t v32;//长度为127时
} ex_len;
uint8_t mkey[4];
uint8_t rh : 1;//head读取完成
uint8_t rl : 1;//len读取完成
uint8_t rk : 1;//mkey读取完成
uint8_t rs : 5;//扩展保留
WebSocketHead(void) { reset(); }
void reset(void) { memset(this,0,sizeof(WebSocketHead)); }
inline uint32_t GetLen(void) {
if (len == 126) {
return ex_len.v16;
} else if (len == 127) {
return ex_len.v32;
}
return len;
}
inline uint8_t GetLenNeedByte(void) {
if (len == 126) {
return 2;
} else if (len == 127) {
return 8;
}
return 0;
}
};
#pragma pack(pop)
enum ConnStatusDef {
CS_CONNED,//连接上
CS_COMMUNICATE,//通信状态
};
typedef std::list<DataPacket*> DataPacketList;
class Client {
public:
Client(GameClientMgr *cli_mgr, SOCKET s, sockaddr_in* addr);
~Client();
//设置阻塞模式。true表示阻塞false表示非阻塞返回值为socket错误号0表示成功
int SetBlockMode(const bool block);
void SetSessionId(const uint16_t sid) { net_id_.index_ = sid; }
uint16_t GetSessionId(void) { return net_id_.index_; }
NetId &GetNetId(void) { return net_id_; }
void RecvData(void);
bool SendData(void);
void WriteEvent(void);
void Flush(const char *buf, size_t len);
void SendNewSession(void);
void SendSessionClose(void);
void Close(void);
bool OnRecv(const char* buf, size_t size);
void FlushWsPack(const char* buf, size_t size);
void OnGameWorldRecv(const char* buf, size_t size);
inline SOCKET GetFd(void) { return fd_; }
inline bool IsClose(void) { return is_close_; }
void PacketHandle(void);
uint16_t GetSKey() { return skey_; }
protected:
void ShakeHandsHandle(const char* buf, int buflen);
private:
inline bool MergePacketList(std::list<DataPacket*>::iterator &dpit);
bool FindHttpParam(const char* param, const char* buf);
bool shake_hands_;//是否已经握手
SOCKET fd_; //套接字
bool is_close_; //是否已经关闭连接
sockaddr_in remote_addr_;//远程地址
DataPacketList recv_list_;//收到的包列表
DataPacket* send_packet_;//需要发包的缓冲区
DataPacketList gw_recv_list_;//从游戏服收到的包列表
WebSocketHead ws_head_;//包头
NetId net_id_;
uint8_t conn_status_;//连接状态
uint16_t skey_;//服务端KEY
static BaseAllocator alloc;
GameClientMgr* cli_mgr_;
char real_ip[64];
};

View File

@@ -0,0 +1,67 @@
#include "StdAfx.h"
#include "client_obj_mgr.h"
#include <map>
ClientObjMgr::ClientObjMgr() {
cur_idx_ = 0;
max_session_ = 0;
}
ClientObjMgr::~ClientObjMgr() {
flush();
for (auto cli:client_list_) {
SafeDelete(cli.second);
}
client_list_.clear();
}
void ClientObjMgr::SetMaxSession(int max_session) {
max_session_ = max_session;
}
bool ClientObjMgr::setNewClient(Client *cli) {
client_lock_.Lock();
if (max_session_ <= cur_idx_) return false;
uint16_t index = 0;
if (free_cli_idx_.empty()) {
index = cur_idx_++;
} else {
index = free_cli_idx_.front();
free_cli_idx_.pop_front();
}
cli->SetSessionId(index);
client_append_list_.push_back(cli);
client_lock_.Unlock();
return true;
}
void ClientObjMgr::flush(void) {
client_lock_.Lock();
for (auto it:client_append_list_) {
client_list_.insert(std::make_pair(it->GetSessionId(), it));
}
client_append_list_.clear();
client_lock_.Unlock();
}
Client* ClientObjMgr::get(uint16_t index) {
auto it = client_list_.find(index);
if (it == client_list_.end()) return NULL;
return it->second;
}
Client * ClientObjMgr::remove(uint16_t index) {
auto it = client_list_.find(index);
if (it == client_list_.end()) return NULL;
Client *cli = it->second;
client_list_.erase(it);
client_lock_.Lock();
if (index == cur_idx_ - 1) {
--cur_idx_;
} else {
free_cli_idx_.push_back(index);
}
client_lock_.Unlock();
return cli;
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include <map>
class ClientObjMgr {
public:
ClientObjMgr();
~ClientObjMgr();
void SetMaxSession(int max_session);
bool setNewClient(Client *cli);
void flush(void);
std::map<uint16_t, Client*> &getClientMap(void) {
return client_list_;
}
Client* get(uint16_t index);
Client* remove(uint16_t index);
private:
uint16_t max_session_;//最大客户端连接数
uint16_t cur_idx_;
std::list<uint16_t> free_cli_idx_;//空闲的客户端索引
std::vector<Client*> client_append_list_;
Mutex client_lock_; //客户端列表锁给append_list用
std::map<uint16_t, Client*> client_list_;
};

View File

@@ -0,0 +1,78 @@
#include "StdAfx.h"
#include "ws_gate_config.h"
const char WsGateConfig::ConfigFileName[] = ("GateWay.txt");
WsGateConfig::WsGateConfig(){
}
WsGateConfig::~WsGateConfig() {
}
void WsGateConfig::showError(const char* err) {
SetErrDesc(err);
RefString s = ("[Config Error]");
s += err;
throw s;
}
bool WsGateConfig::loadServerConfig(GateServer * gate_srv)
{
using namespace stream;
MemoryStream ms(NULL);
try {
if (ms.loadFromFile(ConfigFileName) <= 0) {
showError("unable to load config from file GateWay.txt");
return false;
}
if (!setScript((const char*)ms.getMemory())) {
showError("parse config script failed");
return false;
}
if (openGlobalTable("GateServer")) {
if (enumTableFirst()) {
char str[32];
GameClientMgr* gcmgr = NULL;
do {
if (openFieldTable("LocalService")) {
getFieldStringBuffer(("ServerName"), str, sizeof(str));
gcmgr = gate_srv->AddGameClientMgr(str);
getFieldStringBuffer(("Address"), str, sizeof(str));
gcmgr->SetServiceHost(str);
int port = getFieldInt("Port");
gcmgr->SetServicePort(port);
gcmgr->SetMaxSession(getFieldInt("MaxSession"));
closeTable();
}
if (gcmgr && openFieldTable("BackServer")) {
getFieldStringBuffer(("Host"), str, sizeof(str));
int port = getFieldInt("Port");
gcmgr->InitGameWorldClient(str, port);
closeTable();
}
} while (enumTableNext());
}
closeTable();
}
} catch (RefString& s) {
OutputMsg(rmNormal, s.rawStr());
} catch (...) {
MSG_ERR("unexpected error on load config");
}
return true;
}

View File

@@ -0,0 +1,18 @@
#pragma once
class BaseLuaConfig;
class WsGateConfig :
public BaseLuaConfig {
public:
WsGateConfig();
~WsGateConfig();
static const char ConfigFileName[]; //定义配置文件名称
//加载并读取服务器服务配置
bool loadServerConfig(GateServer *gate_srv);
protected:
void showError(const char* err);
};

View File

@@ -0,0 +1,18 @@
#include "StdAfx.h"
#include "base_event.h"
BaseEvent::BaseEvent(GameClientMgr* cli_mgr)
:cli_mgr_(cli_mgr) {
}
BaseEvent::~BaseEvent()
{
}
bool BaseEvent::init(void) {
return true;
}
void BaseEvent::RunOne(void) {
}

View File

@@ -0,0 +1,16 @@
#pragma once
class BaseEvent
{
public:
BaseEvent(GameClientMgr* cli_mgr);
~BaseEvent();
virtual bool init(void);
virtual void RunOne(void);
virtual void AddReadFd(SOCKET fd, void *ptr = NULL) {}
virtual void DelFd(SOCKET fd, void *ptr = NULL) {}
virtual void AddWriteFd(SOCKET fd, void *ptr = NULL) {}
protected:
GameClientMgr* cli_mgr_;
};

View File

@@ -0,0 +1,52 @@
#include "StdAfx.h"
#include "epoll_event.h"
#ifndef _MSC_VER
EpollEvent::EpollEvent(GameClientMgr* cli_mgr) : BaseEvent(cli_mgr) {
epollfd_ = 0;
listen_fd_ = 0;
}
EpollEvent::~EpollEvent() {
if (epollfd_) {
close(epollfd_);
}
}
bool EpollEvent::init(void) {
epollfd_ = epoll_create(EPOLLEVENTS);
return true;
}
void EpollEvent::RunOne(void) {
int ret = epoll_wait(epollfd_, events_, EPOLLEVENTS, 0);
for (int i = 0; i < ret; i++) {
if (Client *ptr = (Client*)events_[i].data.ptr)
{
if (events_[i].events & EPOLLIN) {
cli_mgr_->HandleReadEvent(ptr->GetFd(), ptr);
} else if (events_[i].events & EPOLLOUT) {
cli_mgr_->HandleWriteEvent(ptr->GetFd(), ptr);
}
}
}
}
void EpollEvent::AddReadFd(SOCKET fd, void *ptr) {
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.ptr = ptr;
epoll_ctl(epollfd_, EPOLL_CTL_ADD, fd, &ev);
}
void EpollEvent::DelFd(SOCKET fd, void *ptr) {
epoll_ctl(epollfd_, EPOLL_CTL_DEL, fd, NULL);
}
void EpollEvent::AddWriteFd(SOCKET fd, void *ptr) {
struct epoll_event ev;
ev.events = EPOLLIN | EPOLLOUT;
ev.data.ptr = ptr;
epoll_ctl(epollfd_, EPOLL_CTL_MOD, fd, &ev);
}
#endif

View File

@@ -0,0 +1,22 @@
#pragma once
#ifndef _MSC_VER
#include "base_event.h"
#include <sys/epoll.h>
#define EPOLLEVENTS 1024
class EpollEvent :
public BaseEvent {
public:
EpollEvent(GameClientMgr* cli_mgr);
~EpollEvent();
virtual bool init(void);
virtual void RunOne(void);
virtual void AddReadFd(SOCKET fd, void *ptr = NULL);
virtual void DelFd(SOCKET fd, void *ptr = NULL);
virtual void AddWriteFd(SOCKET fd, void *ptr = NULL);
private:
SOCKET epollfd_;
SOCKET listen_fd_;
struct epoll_event events_[EPOLLEVENTS];
};
#endif

View File

@@ -0,0 +1,13 @@
#include "StdAfx.h"
#include "select_event.h"
SelectEvent::SelectEvent(GameClientMgr* cli_mgr) : BaseEvent(cli_mgr){
}
SelectEvent::~SelectEvent() {
}
void SelectEvent::RunOne(void) {
cli_mgr_->ProssClient();
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "base_event.h"
#include <map>
class SelectEvent : public BaseEvent {
public:
typedef std::map<SOCKET, void*> FdPtrMap;
SelectEvent(GameClientMgr* cli_mgr);
~SelectEvent();
virtual void RunOne(void);
};

View File

@@ -0,0 +1,144 @@
#include "StdAfx.h"
#include "game_world_client.h"
GameWorldClient::GameWorldClient(GateServer* serv, GameClientMgr* gcmgr, const char* name) :
NetClient(name),
serv_(serv),
gcmgr_(gcmgr) {
SetClientName(name);
free_.setLock(&lock_);
}
GameWorldClient::~GameWorldClient() {
free_.flush();
for (int i = 0; i < free_.count(); i++)
{
DataPacket* dp = free_[i];
dp->setPosition(0);
Flush(*dp);
}
free_.clear();
}
void GameWorldClient::OnRecv(const uint16_t cmd, char * buf, int size)
{
GATEMSGHDR* hdr = (GATEMSGHDR*)buf;
buf = (char*)(hdr + 1);
switch (cmd) {
case GM_DATA: {
//NetId net_id;
//net_id.socket_ = hdr->nSocket;
//net_id.index_ = hdr->wSessionIdx;
//net_id.gate_id_ = hdr->wServerIdx;
DataPacket *dp = AllocPostPacket();
dp->writeBuf(buf , size);
dp->setPosition(0);
GateInterMsg msg;
msg.msg_id_ = gcGWData;
msg.data_.index_ = hdr->wSessionIdx;
msg.data_.packet_ = dp;
gcmgr_->PostMsg(msg);
break;
}
case GM_CLOSE: {
GateInterMsg msg;
msg.msg_id_ = gcGWClose;
msg.data_.index_ = hdr->wSessionIdx;
gcmgr_->PostMsg(msg);
break;
}
case GM_SERVERUSERINDEX: {
GateInterMsg msg;
msg.msg_id_ = gcServerIdx;
msg.data_.idx_ = hdr->wSessionIdx;
msg.data_.para_ = hdr->wServerIdx;
gcmgr_->PostMsg(msg);
break;
}
case GM_CHECKCLIENT: {
break;
}
default:
MSG_LOG("not handle gameword cmd:%d", cmd);
break;
}
}
void GameWorldClient::OnChannelMsg(char* buf, int size) {
Channel info = *((Channel*)buf);
switch (info.type) {
case ccBroadCast: {
uint8_t nsize = sizeof(Channel);
DataPacket *dp = AllocPostPacket();
dp->writeBuf(buf + nsize, size - nsize);
dp->setPosition(0);
GateInterMsg msg;
msg.msg_id_ = gcChBro;
msg.data_.b_channel_ = info.channelId;
msg.data_.b_para_ = info.para;
msg.data_.dp_ = dp;
gcmgr_->PostMsg(msg);
break;
}
case ccAddUser: {
GateInterMsg msg;
msg.msg_id_ = gcChAdd;
msg.data_.channel_ = info.channelId;
msg.data_.para_ = info.para;
msg.data_.idx_ = info.index_;
gcmgr_->PostMsg(msg);
break;
}
case ccDelUser: {
GateInterMsg msg;
msg.msg_id_ = gcChDel;
msg.data_.channel_ = info.channelId;
msg.data_.para_ = info.para;
msg.data_.idx_ = info.index_;
gcmgr_->PostMsg(msg);
break;
}
default:
MSG_LOG("not handle channel type:%d", info.type);
break;
}
}
int GameWorldClient::GetLocalServerType() {
return SrvDef::GateServer;
}
const char * GameWorldClient::GetLocalServerName() {
return gcmgr_->GetServiceName();
}
void GameWorldClient::OnDisconnected() {
GateInterMsg msg;
msg.msg_id_ = gcGWDisconn;
gcmgr_->PostMsg(msg);
}
void GameWorldClient::FreeBackUserDataPacket(DataPacket* pack) {
free_.append(pack);
}
DataPacket* GameWorldClient::AllocPostPacket()
{
if (free_.count() <= 0)
{
free_.flush();
}
if (free_.count() <= 0)
{
AllocSendPack(&free_, 512);
}
DataPacket* dp = free_.pop();//<2F>õ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Datapacket
dp->setLength(0);
return dp;
}

View File

@@ -0,0 +1,34 @@
#pragma once
struct Channel {
int type;// == 0 ? ccAddUser : ccDelUser;
int channelId;
int para;
int index_;
};
class GameWorldClient :
public NetClient
{
public:
GameWorldClient(GateServer* serv, GameClientMgr* gcmgr, const char* name);
~GameWorldClient();
// 回收空闲的CDataPacket类
void FreeBackUserDataPacket(DataPacket* pack);
protected:
// 以下是实现基类的虚函数
virtual void OnRecv(const uint16_t cmd, char* buf, int size);
void OnChannelMsg(char* buf, int size);
virtual int GetLocalServerType();
/* 查询本地服务器的名称,以便正确的发送注册数据 */
virtual const char* GetLocalServerName();
virtual void OnDisconnected();
private:
// 分配一个包,这个包传递给游戏主逻辑处理
DataPacket* AllocPostPacket();
private:
QueueList<DataPacket*> free_; //用来存放空闲的数据包
Mutex lock_;
GateServer* serv_;
GameClientMgr* gcmgr_;
};

View File

@@ -0,0 +1,12 @@
#pragma once
#include <syscall.h>
#define GetCurrentThreadId() syscall(SYS_gettid)
#define MSG_LOG(format, ...) OutputMsg(rmNormal, "[%s:%d %s] "#format, __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__);
#define MSG_WAR(format, ...) OutputMsg(rmWarning, "[%s:%d %s] "#format, __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__);
#define MSG_TIP(format, ...) OutputMsg(rmTip, "[%s:%d %s] "#format, __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__);
#define MSG_ERR(format, ...) OutputMsg(rmError, "[%s:%d %s] "#format, __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__);
#define OrderSwap16(A) (((uint16_t)(A) >> 8) | ((uint16_t)(A & 0xFF) << 8))
#define OrderSwap32(A) (OrderSwap16((uint32_t)(A) >> 16) | ((uint32_t)(OrderSwap16(A)) << 16))
#define OrderSwap64(A) (OrderSwap32((uint64_t)(A) >> 32) | ((uint64_t)(OrderSwap32(A)) << 32));

View File

@@ -0,0 +1,38 @@
#include "StdAfx.h"
GateServer::GateServer() {
GateServer::Instance = this;
GetSystemTime(cur_sys_time_);
now_sec_.encode(cur_sys_time_);
}
GateServer::~GateServer() {
for (auto gcmgr : game_client_mgr_) {
SafeDelete(gcmgr);
}
game_client_mgr_.clear();
}
bool GateServer::StartServer() {
MSG_LOG("start server...................");
for (auto gcmgr : game_client_mgr_) {
gcmgr->Startup();
}
return true;
}
void GateServer::StopServer() {
MSG_LOG("stop server................... start");
for (auto gcmgr : game_client_mgr_) {
gcmgr->Stop();
}
MSG_LOG("stop server................... ok");
}
GameClientMgr* GateServer::AddGameClientMgr(const char *name)
{
GameClientMgr* gcmgr = new GameClientMgr(name, this);
gcmgr->SetServiceName(name);
game_client_mgr_.push_back(gcmgr);
return gcmgr;
}

View File

@@ -0,0 +1,31 @@
#pragma once
class GameClientMgr;
class GateServer {
public:
GateServer();
~GateServer();
//启动服务器
bool StartServer();
//停止服务器
void StopServer();
//获取同步的逻辑短日期时间值
inline unsigned int getMiniDateTime() {
GetSystemTime(cur_sys_time_);
now_sec_.encode(cur_sys_time_);
return now_sec_;
}
GameClientMgr* AddGameClientMgr(const char *name);
public:
static GateServer* Instance;
private:
std::vector<GameClientMgr*> game_client_mgr_;//游戏客户端管理类
SYSTEMTIME cur_sys_time_;
SecondTime now_sec_; //当前短日期时间
};

148
Gateway/gateway/main.cc Normal file
View File

@@ -0,0 +1,148 @@
#include "StdAfx.h"
#include <signal.h>
void Exit() {
#ifdef _MLIB_DUMP_MEMORY_LEAKS_
_CrtDumpMemoryLeaks();
#endif
}
#ifdef _MSC_VER
const char szExceptionDumpFile[] = ".\\wsgate.dmp";
#endif
bool SetupLogicServerConfig(GateServer* gate_srv);
void ServerMain();
GateServer* GateServer::Instance = NULL;
void sighup_handler(int) {
MSG_TIP("log the perfermance ");
MemoryCounter::getSingleton().logToFile();
}
bool runing = false;
void sigterm_handler(int arg) {
sighup_handler(arg);
runing = false;
}
int main(int argc, char** argv) {
winitseed((unsigned int)time(NULL));
#ifdef _MSC_VER
//初始化网络库
int err = WorkSocket::InitSocketLib();
if (err) {
MSG_ERR("initialize inet library failure");
return 0;
}
SetMiniDumpFlag(MiniDumpWithFullMemory, szExceptionDumpFile);
SetUnhandledExceptionFilter(DefaultUnHandleExceptionFilter);
#else
//改为正确的启动目录
const int MAX_PATH = 256;
char startDir[MAX_PATH];
FDOP::ExtractFileDirectory(argv[1], startDir, MAX_PATH - 1);
//merge
char dir[MAX_PATH];
if (startDir[0] == '/') {
SNPRINTFA(dir, MAX_PATH - 1, "%s", startDir);
} else {
char p[MAX_PATH];
getcwd(p, MAX_PATH - 1);
SNPRINTFA(dir, MAX_PATH - 1, "%s/%s", p, startDir);
}
int err = chdir(dir);
printf("chdir:%s, ret:%d\n", dir, err);
//daemon(1, 0);
#endif
InitDefMsgOut();
#ifdef _MSC_VER
TimeProfMgr::getSingleton().InitMgr();
#endif
ServerMain();
MemoryCounter::getSingleton().logToFile();
#ifdef _MSC_VER
TimeProfMgr::getSingleton().clear();
WorkSocket::UnintSocketLib();
#endif
MemoryCounter::getSingleton().clear();
UninitDefMsgOut();
return 0;
}
void ServerMain() {
//设置窗口标题
#ifdef _MSC_VER
SetConsoleTitle("gateway");
#endif
char logpath[256] = "./log/";
if (!FDOP::FileExists(logpath)) {
FDOP::DeepCreateDirectory(logpath);
}
FileLogger flog(("./log/gateway"));
GateServer::Instance = new GateServer();
if (SetupLogicServerConfig(GateServer::Instance)) {
if (GateServer::Instance->StartServer()) {
MSG_TIP("===========================");
MSG_TIP("gateway start ok");
MSG_TIP("quit:stop server and exit");
MSG_TIP("===========================");
#ifndef _MSC_VER
runing = true;
signal(SIGTERM, sigterm_handler);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, sighup_handler);
#endif
while (true) {
#ifdef _MSC_VER
char cmd_buf[512];
//gets(cmd_buf);
scanf("%s", cmd_buf);
if (cmd_buf == NULL || *cmd_buf == 0) {
Sleep(500);
continue;
}
if (strncmp(cmd_buf, ("\\q"), 2) == 0
|| strncmp(cmd_buf, ("exit"), 4) == 0
|| strncmp(cmd_buf, ("quit"), 4) == 0) {
sighup_handler(0);
MSG_TIP("stop gate...");
break;
} else if (strncmp(cmd_buf, "spf", 3) == 0) {
sighup_handler(0);
} else if (strncmp(cmd_buf, "dmp", 3) == 0) {
DebugBreak();
}
#else
if (!runing) break;
#endif
Sleep(10);
}
GateServer::Instance->StopServer();
} else {
MSG_ERR("Press Any Key To Exit...\n");
getc(stdin);
}
}
delete GateServer::Instance;
MSG_LOG("delete GateServer::Instance");
}
bool SetupLogicServerConfig(GateServer* gate_srv) {
WsGateConfig config;
return config.loadServerConfig(gate_srv);
}

View File

@@ -0,0 +1,235 @@
#include "StdAfx.h"
#include <map>
#include "client/client_obj_mgr.h"
#include "event/select_event.h"
#include "event/epoll_event.h"
GameClientMgr::GameClientMgr(const char *name, GateServer *srv) {
srv_ = srv;
gw_cli_ = new GameWorldClient(srv, this, name);
cli_obj_mgr_ = new ClientObjMgr();
inner_msg_list_.setLock(&inner_msg_lock_);
#if USE_EPOLL
event_ = new EpollEvent(this);
#else
event_ = new SelectEvent(this);
#endif
}
GameClientMgr::~GameClientMgr() {
cli_obj_mgr_->flush();
SafeDelete(cli_obj_mgr_);
inner_msg_list_.flush();
inner_msg_list_.clear();
SafeDelete(gw_cli_);
}
void GameClientMgr::SetMaxSession(int max_session) {
cli_obj_mgr_->SetMaxSession(max_session);
}
void GameClientMgr::InitGameWorldClient(const char * ip, int port) {
gw_cli_ = new GameWorldClient(srv_, this, GetServiceName());
gw_cli_->UseBaseAlloc(true);
gw_cli_->SetHost(ip);
gw_cli_->SetPort(port);
}
bool GameClientMgr::onConnect(SOCKET nSocket, sockaddr_in * pAddrIn) {
if (!gw_cli_->connected()) return false;
Client *cli = new Client(this, nSocket, pAddrIn);
cli_obj_mgr_->setNewClient(cli);
cli_obj_mgr_->flush();
cli->SetBlockMode(false);
GateInterMsg msg;
msg.msg_id_ = gcAddClient;
msg.data_.fd_ = nSocket;
msg.data_.sessidx_ = cli->GetSessionId();
PostMsg(msg);
OutputMsg(rmTip, _T("[Login] (1) 客户端连接上来: gatekey(%d)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),
cli->GetSKey(), nSocket, cli->GetNetId().index_, cli->GetNetId().gate_id_, GetCurrentThreadId());
//MSG_TIP("new client connect fd:%d, sid:%d", cli->GetFd(), cli->GetSessionId());
return true;
}
int GameClientMgr::Run() {
inner_msg_list_.flush();
int count = inner_msg_list_.count();
for (int i = 0; i < count; ++i)
{
GateInterMsg& msg = inner_msg_list_[i];
OnRecvSysMsg(msg);
}
inner_msg_list_.clear();
event_->RunOne();
return count;
}
void GameClientMgr::OnStart() {
MSG_LOG("GameClientMgr::OnStart");
event_->init();
}
void GameClientMgr::OnStop() {
MSG_LOG("GameClientMgr::OnStop");
}
void GameClientMgr::Stop() {
MSG_LOG("%s, start", GetServiceName());
while (gw_cli_->GetPacketCount()) {//这里还有包没发完,导致一致没法停止
gw_cli_->SingleRun();
Sleep(1);
}
gw_cli_->Stop();
Inherited::Stop();
MSG_LOG("%s, ok", GetServiceName());
}
void GameClientMgr::OnRecvSysMsg(GateInterMsg & msg)
{
switch (msg.msg_id_)
{
case gcAddClient:
{
event_->AddReadFd(msg.data_.fd_, cli_obj_mgr_->get(msg.data_.sessidx_));
break;
}
case gcServerIdx:
{
Client* cli = cli_obj_mgr_->get(msg.data_.idx_);
if (cli) {
cli->GetNetId().gate_id_ = msg.data_.para_;
OutputMsg(rmTip, _T("[Login] (5) LogicServer已成功添加玩家Gate gatekey(%d)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),
cli->GetSKey(), cli->GetNetId().socket_, cli->GetNetId().index_, cli->GetNetId().gate_id_, GetCurrentThreadId());
}
break;
}
case gcGWData:
{
Client* cli = cli_obj_mgr_->get(msg.data_.index_);
if (cli) {
auto dp = msg.data_.packet_;
cli->OnGameWorldRecv(dp->getOffsetPtr(), dp->getAvaliableLength());
}
gw_cli_->FreeBackUserDataPacket(msg.data_.packet_);
break;
}
case gcGWClose:
{
Client* cli = cli_obj_mgr_->get(msg.data_.index_);
if (cli) {
cli->Close();
}
break;
}
case gcChAdd:
{
uint64_t key = MAKEINT64(msg.data_.channel_, msg.data_.para_);
channel_indexs_map_[key].insert(msg.data_.idx_);
break;
}
case gcChDel:
{
uint64_t key = MAKEINT64(msg.data_.channel_, msg.data_.para_);
channel_indexs_map_[key].erase(msg.data_.idx_);
break;
}
case gcChBro:
{
uint64_t key = MAKEINT64(msg.data_.b_channel_, msg.data_.b_para_);
auto &list = channel_indexs_map_[key];
for (auto idx:list) {
Client* cli = cli_obj_mgr_->get(idx);
if (cli) {
auto dp = msg.data_.packet_;
cli->OnGameWorldRecv(dp->getOffsetPtr(), dp->getAvaliableLength());
}
}
gw_cli_->FreeBackUserDataPacket(msg.data_.dp_);
break;
}
case gcGWDisconn:
{
CloseAllClient();
break;
}
}
}
void GameClientMgr::ProssClient(void) {
//cli_obj_mgr_->flush();
auto &list = cli_obj_mgr_->getClientMap();
std::vector<uint16_t> remove_list;
for (auto it:list) {
Client *cli = it.second;
if(cli)
{
if (cli->IsClose()) {
remove_list.push_back(cli->GetSessionId());
continue;
}
cli->RecvData();
cli->PacketHandle();
cli->WriteEvent();
cli->SendData();
}
}
for (auto idx: remove_list) {
Client *cli = cli_obj_mgr_->remove(idx);
SafeDelete(cli);
}
remove_list.clear();
}
void GameClientMgr::HandleReadEvent(SOCKET fd, Client * cli) {
if (cli) {
cli->RecvData();
cli->PacketHandle();
event_->AddWriteFd(fd, cli);
}
}
void GameClientMgr::HandleWriteEvent(SOCKET fd, Client * cli) {
if (cli) {
cli->WriteEvent();
if (!cli->SendData()) {
event_->AddWriteFd(fd, cli);
}
}
}
void GameClientMgr::CloseAllClient() {
cli_obj_mgr_->flush();
auto &list = cli_obj_mgr_->getClientMap();
std::vector<uint16_t> remove_list;
for (auto it : list) {
Client *cli = it.second;
cli->Close();
}
}
void GameClientMgr::HaveData(Client * cli) {
if(cli) {
event_->AddWriteFd(cli->GetFd(), cli);
}
}
void GameClientMgr::CloseClient(Client * cli) {
event_->DelFd(cli->GetFd());
closesocket(cli->GetFd());
if (cli_obj_mgr_->get(cli->GetSessionId()))
{
cli_obj_mgr_->remove(cli->GetSessionId());
}
}
bool GameClientMgr::Startup() {
if (!Inherited::Startup()) {
return false;
}
// 创建发送线程
return gw_cli_->Startup();
}

View File

@@ -0,0 +1,95 @@
#pragma once
#include <map>
#include <set>
typedef union GateInterMsgData {
struct {
uint32_t b_channel_;
uint32_t b_para_;
DataPacket* dp_;
};
struct {
uint32_t index_;
DataPacket* packet_;
};
struct {
uint32_t idx_;
uint32_t para_;
uint32_t channel_;
};
struct {
uint32_t sessidx_;
SOCKET fd_;
};
} tagGateInterMsgData;
typedef struct GateInterMsg
{
int msg_id_;
GateInterMsgData data_;
} tagGateInterMsg;
class GameWorldClient;
class BaseEvent;
class SocketSrv;
class ClientObjMgr;
enum {
gcAddClient = 1, //增加一个新的客户端连接
gcGWData = 2, //游戏服给客户端发消息
gcGWClose = 3, //游戏服主动关闭客户端
gcChBro = 4,//频道广播消息
gcChAdd = 5,//频道信息增加
gcChDel = 6,//频道信息删除
gcGWDisconn = 7,//游戏服断开连接
gcServerIdx = 8,//游戏服的玩家对应gateid
};
class GameClientMgr : public SocketSrv {
public:
typedef SocketSrv Inherited;
GameClientMgr(const char *name, GateServer *srv);
~GameClientMgr();
void SetMaxSession(int max_session);
bool Startup();
void InitGameWorldClient(const char *ip, int port);
GameWorldClient* GetGameWorldClient(void) { return gw_cli_; }
virtual bool onConnect(SOCKET nSocket, sockaddr_in* pAddrIn);
//单次逻辑处理
virtual int Run();
virtual void OnStart();
virtual void OnStop();
virtual void Stop();
void PostMsg(GateInterMsg& msg) {
inner_msg_list_.append(msg);
}
void OnRecvSysMsg(GateInterMsg& msg);
//select模式使用
void ProssClient(void);
//epoll模式使用
void HandleReadEvent(SOCKET fd, Client* cli);
void HandleWriteEvent(SOCKET fd, Client* cli);
//断开所有客户端连接
void CloseAllClient();
void HaveData(Client* cli);
void CloseClient(Client *cli);
protected:
GateServer *srv_;
GameWorldClient *gw_cli_;
ClientObjMgr *cli_obj_mgr_;
std::map<uint64_t, std::set<int> > channel_indexs_map_;
QueueList<GateInterMsg> inner_msg_list_;//内部消息列表
Mutex inner_msg_lock_;//内部消息列表锁
BaseEvent *event_;//事件处理
};

View File

@@ -0,0 +1,148 @@
#ifdef _MSC_VER
#include <Windows.h>
#include <process.h>
#else
#include <pthread.h>
#endif
#include "StdAfx.h"
#include "socket_srv.h"
SocketSrv::SocketSrv() {
srv_stoped_ = true;
memset(server_name_, 0, sizeof(server_name_));
#ifdef _MSC_VER
accept_thread_ = NULL;
#else
accept_thread_ = 0;
#endif
accept_exit_ = true;
}
SocketSrv::~SocketSrv()
{
#ifdef _MSC_VER
if (NULL != accept_thread_) {
CloseHandle(accept_thread_);
}
accept_thread_ = NULL;
#else
accept_thread_ = 0;
#endif
}
#ifdef _MSC_VER
void STDCALL SocketSrv::ServerSocketAcceptThreadRoutine(void* arg) {
#else
void * SocketSrv::ServerSocketAcceptThreadRoutine(void * arg) {
#endif
SocketSrv *srv = (SocketSrv*)arg;
struct sockaddr_in server_addr;
SOCKET listen_fd_ = 0;
if ((listen_fd_ = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) {
MSG_ERR("create socket error:%d",errno);
assert(false);
}
#ifdef _MSC_VER
char optval = 1;
#else
int optval = 1;
#endif
if (setsockopt(listen_fd_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == SOCKET_ERROR) {
MSG_ERR("setsockopt");
assert(false);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(srv->GetServicePort());
server_addr.sin_addr.s_addr = inet_addr(srv->GetServiceHost());
memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero));
if (::bind(listen_fd_, (struct sockaddr *)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
MSG_ERR("bind error");
assert(false);
}
if (listen(listen_fd_, 5) == SOCKET_ERROR) {
MSG_ERR("listen error");
assert(false);
}
socklen_t len = sizeof(sockaddr);
do {
sockaddr_in cli_addr;
SOCKET nSocket = accept(listen_fd_, (sockaddr*)&cli_addr, &len);
if (srv->Started() && !srv->onConnect(nSocket, &cli_addr)) {
closesocket(nSocket);
}
} while (srv->Started());
closesocket(listen_fd_);
srv->accept_exit_ = true;
#ifdef _MSC_VER
ExitThread(0);//设置线程退出返回值
#else
return NULL;
#endif
}
void SocketSrv::SetServiceName(const char * sName)
{
_STRNCPY_A(server_name_, sName);
}
void SocketSrv::SetServiceHost(const char * sHost)
{
_STRNCPY_A(host_, sHost);
}
void SocketSrv::SetServicePort(const int nPort) {
port_ = nPort;
}
bool SocketSrv::Startup() {
Inherited:Start();
bool ret = true;
int err = 0;
srv_stoped_ = false;
#ifdef _MSC_VER
accept_thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ServerSocketAcceptThreadRoutine, this, 0, NULL);
if (!accept_thread_) {
err = GetLastError();
ret = false;
}
#else
if (pthread_create(&accept_thread_, NULL, ServerSocketAcceptThreadRoutine, this)) {
err = errno;
ret = false;
}
#endif
if (!ret) {
MSG_ERR("create listen thread error %d", err);
return false;
}
accept_exit_ = false;
return true;
}
void SocketSrv::Stop() {
if (srv_stoped_) return;
MSG_LOG("start");
srv_stoped_ = true;
// while (!accept_exit_) {
// Sleep(1);
// }
//#ifdef _MSC_VER
// CloseThread(accept_thread_);
//#endif
Inherited::Stop();
MSG_LOG("ok");
}
void SocketSrv::OnRoutine() {
OnStart();
while (!terminated()) {
if (Run() <= 0)
Sleep(1);
}
OnStop();
}

View File

@@ -0,0 +1,55 @@
#pragma once
class SocketSrv : public thread::BaseThread {
public:
typedef thread::BaseThread Inherited;
SocketSrv();
~SocketSrv();
#ifdef _MSC_VER
static void STDCALL ServerSocketAcceptThreadRoutine(void* srv);
#else
static void* ServerSocketAcceptThreadRoutine(void* arg);
#endif
virtual bool onConnect(SOCKET nSocket, sockaddr_in* pAddrIn) = 0;
virtual void OnRoutine();
//单次逻辑处理
virtual int Run() = 0;
virtual void OnStart() = 0;
virtual void OnStop() = 0;
inline const char* GetServiceName()
{
return server_name_;
}
inline const char* GetServiceHost()
{
return host_;
}
inline int GetServicePort()
{
return port_;
}
inline bool Started()
{
return !srv_stoped_;
}
void SetServiceName(const char* sName);
void SetServiceHost(const char* sHost);
void SetServicePort(const int nPort);
bool Startup();
virtual void Stop();
private:
#ifdef _MSC_VER
HANDLE accept_thread_; //接受客户端连接线程
#else
pthread_t accept_thread_;
#endif
bool srv_stoped_; //是否停止工作线程
bool accept_exit_; //监听线程完整退出
char server_name_[256]; //服务名称
char host_[256]; //服务绑定地址
int port_; //服务绑定端口
};

BIN
Gateway/libs/common.lib Normal file

Binary file not shown.

BIN
Gateway/libs/common.pdb Normal file

Binary file not shown.

BIN
Gateway/libs/libmysql.dll Normal file

Binary file not shown.

BIN
Gateway/libs/libmysql.lib Normal file

Binary file not shown.

Binary file not shown.

BIN
Gateway/srvlib/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,108 @@
MANIFEST contents of Lua 5.1 distribution on Mon Feb 20 11:37:30 BRT 2006
lua-5.1
lua-5.1/COPYRIGHT
lua-5.1/HISTORY
lua-5.1/INSTALL
lua-5.1/MANIFEST
lua-5.1/Makefile
lua-5.1/README
lua-5.1/doc
lua-5.1/doc/contents.html
lua-5.1/doc/logo.gif
lua-5.1/doc/lua.1
lua-5.1/doc/lua.css
lua-5.1/doc/lua.html
lua-5.1/doc/luac.1
lua-5.1/doc/luac.html
lua-5.1/doc/manual.html
lua-5.1/doc/readme.html
lua-5.1/etc
lua-5.1/etc/Makefile
lua-5.1/etc/README
lua-5.1/etc/all.c
lua-5.1/etc/lua.hpp
lua-5.1/etc/lua.ico
lua-5.1/etc/lua.pc
lua-5.1/etc/luavs.bat
lua-5.1/etc/min.c
lua-5.1/etc/noparser.c
lua-5.1/etc/strict.lua
lua-5.1/src
lua-5.1/src/Makefile
lua-5.1/src/lapi.c
lua-5.1/src/lapi.h
lua-5.1/src/lauxlib.c
lua-5.1/src/lauxlib.h
lua-5.1/src/lbaselib.c
lua-5.1/src/lcode.c
lua-5.1/src/lcode.h
lua-5.1/src/ldblib.c
lua-5.1/src/ldebug.c
lua-5.1/src/ldebug.h
lua-5.1/src/ldo.c
lua-5.1/src/ldo.h
lua-5.1/src/ldump.c
lua-5.1/src/lfunc.c
lua-5.1/src/lfunc.h
lua-5.1/src/lgc.c
lua-5.1/src/lgc.h
lua-5.1/src/linit.c
lua-5.1/src/liolib.c
lua-5.1/src/llex.c
lua-5.1/src/llex.h
lua-5.1/src/llimits.h
lua-5.1/src/lmathlib.c
lua-5.1/src/lmem.c
lua-5.1/src/lmem.h
lua-5.1/src/loadlib.c
lua-5.1/src/lobject.c
lua-5.1/src/lobject.h
lua-5.1/src/lopcodes.c
lua-5.1/src/lopcodes.h
lua-5.1/src/loslib.c
lua-5.1/src/lparser.c
lua-5.1/src/lparser.h
lua-5.1/src/lstate.c
lua-5.1/src/lstate.h
lua-5.1/src/lstring.c
lua-5.1/src/lstring.h
lua-5.1/src/lstrlib.c
lua-5.1/src/ltable.c
lua-5.1/src/ltable.h
lua-5.1/src/ltablib.c
lua-5.1/src/ltm.c
lua-5.1/src/ltm.h
lua-5.1/src/lua.c
lua-5.1/src/lua.h
lua-5.1/src/luac.c
lua-5.1/src/luaconf.h
lua-5.1/src/lualib.h
lua-5.1/src/lundump.c
lua-5.1/src/lundump.h
lua-5.1/src/lvm.c
lua-5.1/src/lvm.h
lua-5.1/src/lzio.c
lua-5.1/src/lzio.h
lua-5.1/src/print.c
lua-5.1/test
lua-5.1/test/README
lua-5.1/test/bisect.lua
lua-5.1/test/cf.lua
lua-5.1/test/echo.lua
lua-5.1/test/env.lua
lua-5.1/test/factorial.lua
lua-5.1/test/fib.lua
lua-5.1/test/fibfor.lua
lua-5.1/test/globals.lua
lua-5.1/test/hello.lua
lua-5.1/test/life.lua
lua-5.1/test/luac.lua
lua-5.1/test/printf.lua
lua-5.1/test/readonly.lua
lua-5.1/test/sieve.lua
lua-5.1/test/sort.lua
lua-5.1/test/table.lua
lua-5.1/test/trace-calls.lua
lua-5.1/test/trace-globals.lua
lua-5.1/test/xd.lua
END OF MANIFEST

Some files were not shown because too many files have changed in this diff Show More