美文网首页Golang语言社区LollipopGo游戏服务器框架
LollipopGo开源游戏服务器框架--global服务器源码

LollipopGo开源游戏服务器框架--global服务器源码

作者: Golang语言社区 | 来源:发表于2019-01-07 20:47 被阅读12次

          大家好,我是彬哥,本节给大家讲下LollipopGov1.0.20190102版本游戏服务器globla服务器,抛砖引玉了,主要是针对Go语言游戏服务器Global服务器处理。

    package main
    
    import (
        "LollipopGo/LollipopGo/conf"
        "LollipopGo/LollipopGo/error"
        "LollipopGo/LollipopGo/log"
        "LollipopGo/LollipopGo/match"
        "Proto"
        "Proto/Proto2"
        "flag"
        "fmt"
        "net/rpc"
        "net/rpc/jsonrpc"
        "strings"
        "time"
    
        "LollipopGo/LollipopGo/util"
        "LollipopGo/ReadCSV"
    
        "LollipopGo/LollipopGo/player"
    
        "code.google.com/p/go.net/websocket"
    )
    
    /*
      匹配、活动服务器
        1 匹配玩家活动
    */
    
    var addrG = flag.String("addrG", "127.0.0.1:8888", "http service address")
    var Conn *websocket.Conn
    var ConnRPC *rpc.Client
    
    func init() {
        if !initGateWayNet() {
            fmt.Println("链接 gateway server 失败!")
            return
        }
        fmt.Println("链接 gateway server 成功!")
        initNetRPC()
    
        return
    }
    
    func initNetRPC() {
        client, err := jsonrpc.Dial("tcp", service)
        if err != nil {
            log.Debug("dial error:", err)
            //panic("dial RPC Servre error")
            return
        }
        ConnRPC = client
    }
    
    func initGateWayNet() bool {
        fmt.Println("用户客户端客户端模拟!")
        url := "ws://" + *addrG + "/GolangLtd"
        conn, err := websocket.Dial(url, "", "test://golang/")
        if err != nil {
            fmt.Println("err:", err.Error())
            return false
        }
        Conn = conn
        go GameServerReceiveG(Conn)
        initConn(Conn)
        return true
    }
    
    // 处理数据
    func GameServerReceiveG(ws *websocket.Conn) {
        for {
            var content string
            err := websocket.Message.Receive(ws, &content)
            if err != nil {
                fmt.Println(err.Error())
                continue
            }
            fmt.Println(strings.Trim("", "\""))
            fmt.Println(content)
            content = strings.Replace(content, "\"", "", -1)
            contentstr, errr := base64Decode([]byte(content))
            if errr != nil {
                fmt.Println(errr)
                continue
            }
            go SyncMeassgeFunG(string(contentstr))
        }
    }
    
    // 链接分发 处理
    func SyncMeassgeFunG(content string) {
        var r Requestbody
        r.req = content
    
        if ProtocolData, err := r.Json2map(); err == nil {
            HandleCltProtocolG(ProtocolData["Protocol"], ProtocolData["Protocol2"], ProtocolData)
        } else {
            log.Debug("解析失败:", err.Error())
        }
    }
    
    //  主协议处理
    func HandleCltProtocolG(protocol interface{}, protocol2 interface{}, ProtocolData map[string]interface{}) {
        // defer func() { // 必须要先声明defer,否则不能捕获到panic异常
        //  if err := recover(); err != nil {
        //      strerr := fmt.Sprintf("%s", err)
        //      //发消息给客户端
        //      ErrorST := Proto2.G_Error_All{
        //          Protocol:  Proto.G_Error_Proto,      // 主协议
        //          Protocol2: Proto2.G_Error_All_Proto, // 子协议
        //          ErrCode:   "80006",
        //          ErrMsg:    "亲,您发的数据的格式不对!" + strerr,
        //      }
        //      // 发送给玩家数据
        //      fmt.Println("Global server的主协议!!!", ErrorST)
        //  }
        // }()
    
        // 协议处理
        switch protocol {
        case float64(Proto.G_GameGlobal_Proto):
            { // Global Server 主要协议处理
                fmt.Println("Global server 主协议!!!")
                HandleCltProtocol2Glogbal(protocol2, ProtocolData)
    
            }
        default:
            panic("主协议:不存在!!!")
        }
        return
    }
    
    // 子协议的处理
    func HandleCltProtocol2Glogbal(protocol2 interface{}, ProtocolData map[string]interface{}) {
    
        switch protocol2 {
        case float64(Proto2.GW2G_ConnServerProto2):
            { // 网关返回数据
                fmt.Println("gateway server 返回给global server 数据信息!!!")
            }
        case float64(Proto2.G2GW_PlayerEntryHallProto2):
            {
                G2GW_PlayerEntryHallProto2Fucn(Conn, ProtocolData)
            }
        case float64(Proto2.G2GW_PlayerMatchGameProto2):
            {
                fmt.Println("玩家请求玩家匹配!")
                G2GW_PlayerMatchGameProto2Fucn(Conn, ProtocolData)
            }
        case float64(Proto2.GW2G_PlayerQuitMatchGameProto2):
            {
                fmt.Println("玩家主动退出匹配!")
                G2GW_PlayerQuitMatchGameProto2Fucn(Conn, ProtocolData)
            }
        default:
            panic("子协议:不存在!!!")
        }
        return
    }
    
    // 玩家主动退出匹配
    func G2GW_PlayerQuitMatchGameProto2Fucn(conn *websocket.Conn, ProtocolData map[string]interface{}) {
        if ProtocolData["OpenID"] == nil {
            panic("玩家主动退出匹配!")
            return
        }
        StrOpenID := ProtocolData["OpenID"].(string)
        // 玩家主动退出
        match.SetQuitMatch(StrOpenID)
        // 发送消息
        data_send := &Proto2.G2GW_PlayerQuitMatchGame{
            Protocol:  Proto.G_GameGlobal_Proto,
            Protocol2: Proto2.G2GW_PlayerQuitMatchGameProto2,
            OpenID:    StrOpenID,
            ResultID:  0,
        }
        PlayerSendToServer(conn, data_send)
        return
    }
    
    // 玩家匹配
    func G2GW_PlayerMatchGameProto2Fucn(conn *websocket.Conn, ProtocolData map[string]interface{}) {
        if ProtocolData["OpenID"] == nil ||
            ProtocolData["RoomID"] == nil ||
            ProtocolData["Itype"] == nil {
            panic("选择游戏对战类型协议参数错误!")
            return
        }
        StrOpenID := ProtocolData["OpenID"].(string)
        StrRoomID := ProtocolData["RoomID"].(string) //  匹配数据
        StrItype := ProtocolData["Itype"].(string)   //  1 是正常匹配 2 是快速匹配
    
        // 数据
        data_send := &Proto2.GW2G_PlayerMatchGame{
            Protocol:  Proto.G_GameGlobal_Proto, // 游戏主要协议
            Protocol2: Proto2.GW2G_PlayerMatchGameProto2,
            OpenID:    StrOpenID, // 玩家唯一标识
            // RoomUID:     0,
            // MatchPlayer: nil,
            // ChessBoard:  {{}, {}, {}, {}},
            ResultID: 0,
        }
        if match.GetMatchQueue(StrOpenID) {
            data_send.ResultID = Error.IsMatch
            PlayerSendToServer(conn, data_send)
            return
        }
        match.SetMatchQueue(StrOpenID)
    
        if StrItype == "2" { //快速匹配
            PlayerSendToServer(conn, data_send)
            return
        }
    
        data := conf.RoomListDatabak[StrRoomID]
        fmt.Println("针对某房间ID去获取,相应的数据的", conf.RoomListDatabak, data.NeedLev, StrRoomID)
        dataplayer := DB_Save_RoleSTBak(StrOpenID)
        match.Putdata(dataplayer)
        s := string([]byte(data.NeedLev)[2:])
        if util.Str2int_LollipopGo(s) > dataplayer.Lev {
            data_send.ResultID = Error.Lev_lack
            PlayerSendToServer(conn, data_send)
            return
        } else if util.Str2int_LollipopGo(data.NeedPiece) > dataplayer.CoinNum {
            data_send.ResultID = Error.Coin_lack
            PlayerSendToServer(conn, data_send)
            return
        }
    
        if len(match.MatchData) > 1 {
            dar := <-match.MatchData_Chan
            data_send.MatchPlayer = dar
            fmt.Println(data_send)
            PlayerSendToServer(conn, data_send)
            match.DelMatchQueue(StrOpenID)
        } else {
            go PlayerMatchTime(conn, StrOpenID, data_send)
        }
    
        return
    }
    
    func PlayerMatchTime(conn *websocket.Conn, OpenID string, data_send *Proto2.GW2G_PlayerMatchGame) {
        icount := 0
        for {
            select {
            case <-time.After(match.PlaterMatchSpeed):
                {
                    fmt.Println(icount)
                    if icount >= 30 {
                        PlayerSendToServer(conn, data_send)
                        return
                    }
    
                    if len(match.MatchData_Chan) > 1 {
                        dar := <-match.MatchData_Chan
                        data_send.MatchPlayer = dar
                        fmt.Println(data_send)
                        PlayerSendToServer(conn, data_send)
                        match.DelMatchQueue(OpenID)
                        return
                    }
                    icount++
                }
            }
        }
    }
    
    // 保存数据都DB 人物信息
    func DB_Save_RoleSTBak(openid string) *player.PlayerSt {
    
        args := player.PlayerSt{
            OpenID: openid,
        }
    
        var reply *player.PlayerSt
        // 异步调用【结构的方法】
        if ConnRPC != nil {
            // ConnRPC.Call("Arith.GetPlayerST2DB", args, &reply) 同步调用
            divCall := ConnRPC.Go("Arith.GetPlayerST2DB", args, &reply, nil)
            replyCall := <-divCall.Done
            _ = replyCall.Reply
        } else {
            fmt.Println("ConnRPC == nil")
        }
        return reply
    }
    
    func G2GW_PlayerEntryHallProto2Fucn(conn *websocket.Conn, ProtocolData map[string]interface{}) {
    
        StrUID := ProtocolData["UID"].(string)
        StrOpenID := ProtocolData["OpenID"].(string)
        StrPlayerName := ProtocolData["PlayerName"].(string)
        StrHeadUrl := ProtocolData["HeadUrl"].(string)
        StrSex := ProtocolData["Sex"].(string)
        StrConstellation := ProtocolData["Constellation"].(string)
        StrPlayerSchool := ProtocolData["PlayerSchool"].(string)
        StrToken := ProtocolData["Token"].(string)
        _ = StrToken
    
        // 获取在线人数
        ddd := make(map[string]interface{})
        csv.M_CSV.LollipopGo_RLockRange(ddd)
        // 查询数据库,找出游戏服务器的uid信息
        // 返回的数据操作
        datadb := DB_Save_RoleST(StrUID, StrPlayerName, StrHeadUrl, StrPlayerSchool, StrSex, StrConstellation, 0, 0, 2000, 0, 0)
        fmt.Println("--------------------------:", datadb)
        // 个人数据
        personalmap := make(map[string]*player.PlayerSt)
        personalmap["1"] = &datadb
        _ = personalmap["1"].OpenID
    
        // 组装数据
        data := &Proto2.GW2G_PlayerEntryHall{
            Protocol:      Proto.G_GameGlobal_Proto, // 游戏主要协议
            Protocol2:     Proto2.GW2G_PlayerEntryHallProto2,
            OpenID:        StrOpenID,
            PlayerName:    StrPlayerName,
            HeadUrl:       StrHeadUrl,
            Constellation: StrConstellation,
            Sex:           StrSex,
            GamePlayerNum: ddd,
            RacePlayerNum: nil,
            Personal:      personalmap,
            DefaultMsg:    nil,
            DefaultAward:  nil,
        }
        fmt.Println(data)
        PlayerSendToServer(conn, data)
        // 保存玩家的数据  -- 主要是为了
        return
    
    }
    
    // 保存数据都DB 人物信息
    func DB_Save_RoleST(uid, strname, HeadURL, StrPlayerSchool, Sex, Constellation string, Lev, HallExp, CoinNum, MasonryNum, MCard int) player.PlayerSt {
    
        args := player.PlayerSt{
            UID:           util.Str2int_LollipopGo(uid),
            VIP_Lev:       0,
            Name:          strname,
            HeadURL:       HeadURL,
            Sex:           Sex,
            PlayerSchool:  StrPlayerSchool,
            Lev:           Lev,
            HallExp:       HallExp,
            CoinNum:       CoinNum,
            MasonryNum:    MasonryNum,
            MCard:         MCard,
            Constellation: Constellation,
            OpenID:        util.MD5_LollipopGO(uid),
        }
    
        var reply player.PlayerSt
        // 异步调用【结构的方法】
        if ConnRPC != nil {
            // ConnRPC.Call("Arith.SavePlayerST2DB", args, &reply) 同步调用
            divCall := ConnRPC.Go("Arith.SavePlayerST2DB", args, &reply, nil)
            replyCall := <-divCall.Done
            _ = replyCall.Reply
        } else {
            fmt.Println("ConnRPC == nil")
        }
        return reply
    }
    
    func initConn(conn *websocket.Conn) {
        data := &Proto2.G2GW_ConnServer{
            Protocol:  Proto.G_GameGlobal_Proto,
            Protocol2: Proto2.G2GW_ConnServerProto2,
            ServerID:  util.MD5_LollipopGO("8894" + "Global server"),
        }
        PlayerSendToServer(conn, data)
        return
    }
    
    

          每天坚持学习1小时Go语言,大家加油,我是彬哥,下期见!如果文章中不同观点、意见请文章下留言或者关注下方订阅号反馈!


    社区交流群:221273219
    Golang语言社区论坛 :
    www.Golang.Ltd
    LollipopGo游戏服务器地址:
    https://github.com/Golangltd/LollipopGo
    社区视频课程课件GIT地址:
    https://github.com/Golangltd/codeclass


    Golang语言社区

    相关文章

      网友评论

        本文标题:LollipopGo开源游戏服务器框架--global服务器源码

        本文链接:https://www.haomeiwen.com/subject/nfvprqtx.html