mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 15:52:27 +08:00
客户端协议代理功能
This commit is contained in:
16
gate/client_proto/README.md
Normal file
16
gate/client_proto/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# 客户端协议代理功能
|
||||
|
||||
## 功能介绍
|
||||
|
||||
### 开启本功能后,网关服务器以及游戏服务器等其他服务器,将预先对客户端上行和服务器下行的协议数据做前置转换,采用任意版本的协议文件(必要字段名必须与现有的协议保持一致)均可,避免了因协议序号混淆等频繁变动,而造成游戏服务器代码不必要的频繁改动
|
||||
|
||||
## 使用方法
|
||||
|
||||
1. 在此目录下建立bin目录和proto目录
|
||||
2. 将client_cmd.csv文件放到bin目录下
|
||||
3. 将对应版本的proto协议文件复制到proto目录下并编译成pb.go
|
||||
4. 将client_proto_gen_test.go的TestClientProtoGen方法添加运行配置
|
||||
5. 将运行配置输出目录和工作目录都设置为bin目录
|
||||
6. 运行并生成client_proto_gen.go
|
||||
7. 将client_cmd.csv放入gate和gs和fight服务器的运行目录下
|
||||
8. 将gate和gs和fight服务器的配置文件中开启client_proto_proxy_enable客户端协议代理功能
|
||||
@@ -2,11 +2,23 @@ package client_proto
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestClientProtoGen(t *testing.T) {
|
||||
clientCmdProtoMap := NewClientCmdProtoMap()
|
||||
dir, err := os.ReadDir("../proto")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
nameList := make([]string, 0)
|
||||
for _, entry := range dir {
|
||||
split := strings.Split(entry.Name(), ".")
|
||||
if len(split) != 2 {
|
||||
panic("file name error")
|
||||
}
|
||||
nameList = append(nameList, split[0])
|
||||
}
|
||||
|
||||
fileData := "package client_proto\n"
|
||||
fileData += "\n"
|
||||
@@ -15,10 +27,10 @@ func TestClientProtoGen(t *testing.T) {
|
||||
fileData += "pb \"google.golang.org/protobuf/proto\"\n"
|
||||
fileData += ")\n"
|
||||
fileData += "\n"
|
||||
fileData += "func (c *ClientCmdProtoMap) GetClientProtoObjByCmdName(cmdName string) pb.Message {\n"
|
||||
fileData += "switch cmdName {\n"
|
||||
for cmdName := range clientCmdProtoMap.clientCmdNameCmdIdMap {
|
||||
fileData += "case \"" + cmdName + "\":\nreturn new(proto." + cmdName + ")\n"
|
||||
fileData += "func (c *ClientCmdProtoMap) GetClientProtoObjByName(protoObjName string) pb.Message {\n"
|
||||
fileData += "switch protoObjName {\n"
|
||||
for _, protoObjName := range nameList {
|
||||
fileData += "case \"" + protoObjName + "\":\nreturn new(proto." + protoObjName + ")\n"
|
||||
}
|
||||
fileData += "default:\n"
|
||||
fileData += "return nil\n"
|
||||
@@ -26,7 +38,7 @@ func TestClientProtoGen(t *testing.T) {
|
||||
fileData += "}\n"
|
||||
fileData += "\n"
|
||||
|
||||
err := os.WriteFile("../client_proto_gen.go", []byte(fileData), 0644)
|
||||
err = os.WriteFile("../client_proto_gen.go", []byte(fileData), 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -53,8 +53,10 @@ func NewKcpConnectManager(messageQueue *mq.MessageQueue, discovery *rpc.Discover
|
||||
r.kcpEventInput = make(chan *KcpEvent, 1000)
|
||||
r.kcpEventOutput = make(chan *KcpEvent, 1000)
|
||||
r.serverCmdProtoMap = cmd.NewCmdProtoMap()
|
||||
r.clientCmdProtoMap = client_proto.NewClientCmdProtoMap()
|
||||
r.clientCmdProtoMapRefValue = reflect.ValueOf(r.clientCmdProtoMap)
|
||||
if config.CONF.Hk4e.ClientProtoProxyEnable {
|
||||
r.clientCmdProtoMap = client_proto.NewClientCmdProtoMap()
|
||||
r.clientCmdProtoMapRefValue = reflect.ValueOf(r.clientCmdProtoMap)
|
||||
}
|
||||
r.messageQueue = messageQueue
|
||||
r.localMsgOutput = make(chan *ProtoMsg, 1000)
|
||||
r.createSessionChan = make(chan *Session, 1000)
|
||||
|
||||
@@ -30,21 +30,38 @@ func (k *KcpConnectManager) protoDecode(kcpMsg *KcpMsg) (protoMsgList []*ProtoMs
|
||||
clientCmdId := kcpMsg.CmdId
|
||||
clientProtoData := kcpMsg.ProtoData
|
||||
cmdName := k.clientCmdProtoMap.GetClientCmdNameByCmdId(clientCmdId)
|
||||
clientProtoObj := k.clientCmdProtoMapRefValue.MethodByName(
|
||||
"GetClientProtoObjByCmdName",
|
||||
).Call([]reflect.Value{reflect.ValueOf(cmdName)})[0].Interface().(pb.Message)
|
||||
if cmdName == "" {
|
||||
logger.Error("get cmdName is nil, clientCmdId: %v", clientCmdId)
|
||||
return protoMsgList
|
||||
}
|
||||
clientProtoObj := k.getClientProtoObjByName(cmdName)
|
||||
if clientProtoObj == nil {
|
||||
logger.Error("get client proto obj is nil, cmdName: %v", cmdName)
|
||||
return protoMsgList
|
||||
}
|
||||
err := pb.Unmarshal(clientProtoData, clientProtoObj)
|
||||
if err != nil {
|
||||
logger.Error("unmarshal client proto error: %v", err)
|
||||
return protoMsgList
|
||||
}
|
||||
serverCmdId := k.serverCmdProtoMap.GetCmdIdByCmdName(cmdName)
|
||||
if serverCmdId == 0 {
|
||||
logger.Error("get server cmdId is nil, cmdName: %v", cmdName)
|
||||
return protoMsgList
|
||||
}
|
||||
serverProtoObj := k.serverCmdProtoMap.GetProtoObjByCmdId(serverCmdId)
|
||||
err = object.CopyProtoBufSameField(serverProtoObj, clientProtoObj)
|
||||
if serverProtoObj == nil {
|
||||
logger.Error("get server proto obj is nil, serverCmdId: %v", serverCmdId)
|
||||
return protoMsgList
|
||||
}
|
||||
delList, err := object.CopyProtoBufSameField(serverProtoObj, clientProtoObj)
|
||||
if err != nil {
|
||||
logger.Error("copy proto obj error: %v", err)
|
||||
return protoMsgList
|
||||
}
|
||||
if len(delList) != 0 {
|
||||
logger.Error("delete field name list: %v, cmdName: %v", delList, cmdName)
|
||||
}
|
||||
serverProtoData, err := pb.Marshal(serverProtoObj)
|
||||
if err != nil {
|
||||
logger.Error("marshal server proto error: %v", err)
|
||||
@@ -117,6 +134,50 @@ func (k *KcpConnectManager) protoDecodePayloadLoop(cmdId uint16, protoData []byt
|
||||
return
|
||||
}
|
||||
for _, unionCmd := range unionCmdNotify.GetCmdList() {
|
||||
if config.CONF.Hk4e.ClientProtoProxyEnable {
|
||||
clientCmdId := uint16(unionCmd.MessageId)
|
||||
clientProtoData := unionCmd.Body
|
||||
cmdName := k.clientCmdProtoMap.GetClientCmdNameByCmdId(clientCmdId)
|
||||
if cmdName == "" {
|
||||
logger.Error("get cmdName is nil, clientCmdId: %v", clientCmdId)
|
||||
continue
|
||||
}
|
||||
clientProtoObj := k.getClientProtoObjByName(cmdName)
|
||||
if clientProtoObj == nil {
|
||||
logger.Error("get client proto obj is nil, cmdName: %v", cmdName)
|
||||
continue
|
||||
}
|
||||
err := pb.Unmarshal(clientProtoData, clientProtoObj)
|
||||
if err != nil {
|
||||
logger.Error("unmarshal client proto error: %v", err)
|
||||
continue
|
||||
}
|
||||
serverCmdId := k.serverCmdProtoMap.GetCmdIdByCmdName(cmdName)
|
||||
if serverCmdId == 0 {
|
||||
logger.Error("get server cmdId is nil, cmdName: %v", cmdName)
|
||||
continue
|
||||
}
|
||||
serverProtoObj := k.serverCmdProtoMap.GetProtoObjByCmdId(serverCmdId)
|
||||
if serverProtoObj == nil {
|
||||
logger.Error("get server proto obj is nil, serverCmdId: %v", serverCmdId)
|
||||
continue
|
||||
}
|
||||
delList, err := object.CopyProtoBufSameField(serverProtoObj, clientProtoObj)
|
||||
if err != nil {
|
||||
logger.Error("copy proto obj error: %v", err)
|
||||
continue
|
||||
}
|
||||
if len(delList) != 0 {
|
||||
logger.Error("delete field name list: %v, cmdName: %v", delList, cmdName)
|
||||
}
|
||||
serverProtoData, err := pb.Marshal(serverProtoObj)
|
||||
if err != nil {
|
||||
logger.Error("marshal server proto error: %v", err)
|
||||
continue
|
||||
}
|
||||
unionCmd.MessageId = uint32(serverCmdId)
|
||||
unionCmd.Body = serverProtoData
|
||||
}
|
||||
k.protoDecodePayloadLoop(uint16(unionCmd.MessageId), unionCmd.Body, protoMessageList)
|
||||
}
|
||||
}
|
||||
@@ -165,24 +226,43 @@ func (k *KcpConnectManager) protoEncode(protoMsg *ProtoMsg) (kcpMsg *KcpMsg) {
|
||||
serverCmdId := kcpMsg.CmdId
|
||||
serverProtoData := kcpMsg.ProtoData
|
||||
serverProtoObj := k.serverCmdProtoMap.GetProtoObjByCmdId(serverCmdId)
|
||||
if serverProtoObj == nil {
|
||||
logger.Error("get server proto obj is nil, serverCmdId: %v", serverCmdId)
|
||||
return nil
|
||||
}
|
||||
err := pb.Unmarshal(serverProtoData, serverProtoObj)
|
||||
if err != nil {
|
||||
logger.Error("unmarshal server proto error: %v", err)
|
||||
return nil
|
||||
}
|
||||
cmdName := k.serverCmdProtoMap.GetCmdNameByCmdId(serverCmdId)
|
||||
clientProtoObj := k.clientCmdProtoMapRefValue.MethodByName(
|
||||
"GetClientProtoObjByCmdName",
|
||||
).Call([]reflect.Value{reflect.ValueOf(cmdName)})[0].Interface().(pb.Message)
|
||||
err = object.CopyProtoBufSameField(clientProtoObj, serverProtoObj)
|
||||
if cmdName == "" {
|
||||
logger.Error("get cmdName is nil, serverCmdId: %v", serverCmdId)
|
||||
return nil
|
||||
}
|
||||
clientProtoObj := k.getClientProtoObjByName(cmdName)
|
||||
if clientProtoObj == nil {
|
||||
logger.Error("get client proto obj is nil, cmdName: %v", cmdName)
|
||||
return nil
|
||||
}
|
||||
delList, err := object.CopyProtoBufSameField(clientProtoObj, serverProtoObj)
|
||||
if err != nil {
|
||||
logger.Error("copy proto obj error: %v", err)
|
||||
return nil
|
||||
}
|
||||
if len(delList) != 0 {
|
||||
logger.Error("delete field name list: %v, cmdName: %v", delList, cmdName)
|
||||
}
|
||||
clientProtoData, err := pb.Marshal(clientProtoObj)
|
||||
if err != nil {
|
||||
logger.Error("marshal client proto error: %v", err)
|
||||
return nil
|
||||
}
|
||||
clientCmdId := k.clientCmdProtoMap.GetClientCmdIdByCmdName(cmdName)
|
||||
if clientCmdId == 0 {
|
||||
logger.Error("get client cmdId is nil, cmdName: %v", cmdName)
|
||||
return nil
|
||||
}
|
||||
kcpMsg.CmdId = clientCmdId
|
||||
kcpMsg.ProtoData = clientProtoData
|
||||
}
|
||||
@@ -213,3 +293,10 @@ func (k *KcpConnectManager) encodeProtoToPayload(protoObj pb.Message) (cmdId uin
|
||||
}
|
||||
return cmdId, protoData
|
||||
}
|
||||
|
||||
func (k *KcpConnectManager) getClientProtoObjByName(protoObjName string) pb.Message {
|
||||
clientProtoObj := k.clientCmdProtoMapRefValue.MethodByName(
|
||||
"GetClientProtoObjByName",
|
||||
).Call([]reflect.Value{reflect.ValueOf(protoObjName)})[0].Interface().(pb.Message)
|
||||
return clientProtoObj
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user