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

Golang语言社区 · · 2510 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

      大家好,我是彬哥,本节给大家讲下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语言社区

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:Golang语言社区

查看原文:LollipopGo开源游戏服务器框架--global服务器源码

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2510 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传