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

栏目: Go · 发布时间: 5年前

内容简介:大家好,我是彬哥,本节给大家讲下LollipopGov1.0.20190102版本游戏服务器globla服务器,抛砖引玉了,主要是针对Go语言游戏服务器Global服务器处理。每天坚持学习1小时Go语言,大家加油,我是彬哥,下期见!如果文章中不同观点、意见请文章下留言或者关注下方订阅号反馈!

大家好,我是彬哥,本节给大家讲下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)
        }
    case float64(Proto2.GW2G_GetPlayerEmailListProto2):
        {
            fmt.Println("获取玩家邮件列表!")
            G2GW_PlayerGetPlayerEmailListProto2Fucn(Conn, ProtocolData)
        }
    case float64(Proto2.GW2G_ReadOrDelPlayerEmailProto2):
        {
            fmt.Println("玩家邮件列表读取!")
            G2GW_PlayerReadOrDelPlayerEmailProto2Fucn(Conn, ProtocolData)
        }
    default:
        panic("子协议:不存在!!!")
    }
    return
}

func G2GW_PlayerReadOrDelPlayerEmailProto2Fucn(conn *websocket.Conn, ProtocolData map[string]interface{}) {
    if ProtocolData["OpenID"] == nil {
        panic("读取邮件错误!")
    }
    StrOpenID := ProtocolData["OpenID"].(string)
    iItype := int(ProtocolData["Itype"].(float64))
    iEmailID := int(ProtocolData["EmailID"].(float64))

    data_send := &Proto2.G2GW_ReadOrDelPlayerEmail{
        Protocol:  Proto.G_GameGlobal_Proto,
        Protocol2: Proto2.G2GW_ReadOrDelPlayerEmailProto2,
        OpenID:    StrOpenID,
        Itype:     iItype,
    }
    // 1:读取打开,2:删除,3:领取附件
    if iItype == 1 {
        if EmailDatatmp[iEmailID] == nil {
            EmailDatatmp[iEmailID].IsOpen = true
            data_send.Itype = 0
        }
    } else if iItype == 2 {
        delete(EmailDatatmp, iEmailID)
    } else if iItype == 3 {
        EmailDatatmp[iEmailID].IsAdd_ons = true
    }

    PlayerSendToServer(conn, data_send)
    return
}

//------------------------------------------------------------------------------

var EmailDatatmp map[int]*player.EmailST
var ItemListtmp map[int]*player.ItemST
var PaoMaDeng map[int]*player.MsgST

func init() {
    EmailDatatmp = make(map[int]*player.EmailST)
    ItemListtmp = make(map[int]*player.ItemST)
    PaoMaDeng = make(map[int]*player.MsgST)

    if true {
        data := new(player.EmailST)
        data.ID = 1
        data.Name = "测试邮件1"
        data.Time = int(util.GetNowUnix_LollipopGo())
        data.Content = "测试邮件内容1"
        data.IsAdd_ons = false
        data.IsOpen = false
        EmailDatatmp[data.ID] = data
    }

    if true {
        data := new(player.EmailST)
        data.ID = 2
        data.Name = "测试邮件2"
        data.Time = int(util.GetNowUnix_LollipopGo())
        data.Content = "测试邮件内容2"
        data.IsAdd_ons = false
        data.IsOpen = false
        EmailDatatmp[data.ID] = data
    }

    if true {
        data := new(player.EmailST)
        data.ID = 3
        data.Name = "测试邮件3"
        data.Time = int(util.GetNowUnix_LollipopGo())
        data.Content = "测试邮件内容3"
        data.IsAdd_ons = true
        data.IsOpen = false

        if true {
            dataitem := new(player.ItemST)
            dataitem.ID = 1
            dataitem.Icon = ""
            dataitem.Name = "M卡"
            dataitem.Itype = 1
            dataitem.Num = 10
            ItemListtmp[dataitem.ID] = dataitem
        }

        data.ItemList = ItemListtmp
        EmailDatatmp[data.ID] = data
    }
    //--------------------------------------------------------------------------
    // DefaultMsg    map[string]*player.MsgST    // 默认跑马灯消息
    if true {
        data := new(player.MsgST)
        data.MsgID = 1
        data.MsgType = player.MsgType1
        data.MsgDesc = "系统消息:充值998,送B站24K纯金哥斯拉"
        PaoMaDeng[data.MsgID] = data
    }
    if true {
        data := new(player.MsgST)
        data.MsgID = 2
        data.MsgType = player.MsgType2
        data.MsgDesc = "恭喜【XXX玩家】在XX比赛中获得xxx奖励"
        PaoMaDeng[data.MsgID] = data
    }
    if true {
        data := new(player.MsgST)
        data.MsgID = 3
        data.MsgType = player.MsgType3
        data.MsgDesc = "恭喜【XXX玩家】在兑换中心成功兑换SSS"
        PaoMaDeng[data.MsgID] = data
    }
    return
}

//------------------------------------------------------------------------------

func G2GW_PlayerGetPlayerEmailListProto2Fucn(conn *websocket.Conn, ProtocolData map[string]interface{}) {
    if ProtocolData["OpenID"] == nil {
        panic("获取玩家列表!")
    }
    StrOpenID := ProtocolData["OpenID"].(string)

    data_send := &Proto2.G2GW_GetPlayerEmailList{
        Protocol:  Proto.G_GameGlobal_Proto,
        Protocol2: Proto2.G2GW_GetPlayerEmailListProto2,
        OpenID:    StrOpenID,
        EmailData: EmailDatatmp,
    }
    PlayerSendToServer(conn, data_send)
    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:    PaoMaDeng,
        DefaultAward:  nil,
        IsNewEmail:    true,
    }
    if len(EmailDatatmp) == 0 {
        data.IsNewEmail = false
    }
    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
LollipopGo开源游戏服务器框架--global服务器源码2

Golang语言社区


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Cracking the Coding Interview

Cracking the Coding Interview

Gayle Laakmann McDowell / CareerCup / 2015-7-1 / USD 39.95

Cracking the Coding Interview, 6th Edition is here to help you through this process, teaching you what you need to know and enabling you to perform at your very best. I've coached and interviewed hund......一起来看看 《Cracking the Coding Interview》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具