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

大家好,我是彬哥,本节给大家讲下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 :=

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

{

fmt.Println(icount)

if icount >= 30 {

PlayerSendToServer(conn, data_send)

return

}

if len(match.MatchData_Chan) > 1 {

dar :=

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 :=

_ = 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 :=

_ = 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语言,大家加油,我是彬哥,下期见!如果文章中不同观点、意见请文章下留言或者关注下方订阅号反馈!

6b2ac594919b?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

Golang语言社区

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288109.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ArcGIS导入Sketchup模型

ArcGIS可以与Sketchup、3D Studio Max等三维软件完美进行交互。 ArcGIS可以借助 Import 3D Files 工具支持主流的三维模型导入。支持 3D Studio Max (*.3ds)、VRML and GeoVRML 2.0 (*.wrl)、SketchUp 6.0 (*.skp)、OpenFlight 15.8 (*.flt)、Collaborative Design Activity (C…

剑指offer之两个队列实现栈的问题

1 问题 两个队列实现栈的插入和获取头部元素的功能 2 分析 1)获取头部元素的功能分析: 我们有2个队列,我们知道队列的特点的先进先出,而栈的特点是先进后出,比如我们有数据1,2,3,4,我们分别依次压入队列1&#xff0…

solr的空间查询(查询地图周围坐标)

原文网址:http://www.cnblogs.com/hanhuibing/articles/5680616.html 基于Solr的空间搜索 如果需要对带经纬度的数据进行检索,比如查找当前所在位置附近1000米的酒店,一种简单的方法就是:获取数据库中的所有酒店数据,…

「零门槛多语言 Python/C/C# 通用思想学习系列」第一篇:经典HelloWorld

环境说明 操作系统:Windows7 SP1 编辑器说明: Python:notepadC:devcC sharp(C#):Visual Studio2019 注意: 标点:在编程中要使用英文的标点符号,必须切记数…

服务器2008 系统日志 提示打印机,介绍服务器日志出现打印机错误的解决方法

今天来聊聊一篇关于服务器日志出现打印机错误的解决方法的文章,现在就为大家来简单介绍下服务器日志出现打印机错误的解决方法,希望对各位小伙伴们有所帮助。windows2003日志提示,打印机 ****未知。登录之前,请与管理员联系,安装驱动程序。事…

js 错误/异常处理

为什么80%的码农都做不了架构师?>>> /*** 自定义错误处理*/ onerror handleError; function handleError(desc,page,line){alert("desc:"desc"\n""page:"page"\n""line:"line); } var s null; s.t…

多面体 (Multipatch)

多面体要素是一种可存储面集合的 GIS 对象,能够在数据库中将 3D 对象的边界表示为单个行。面可存储表示要素组成部分的纹理、颜色、透明度和几何信息。面中存储的几何信息可以是三角形、三角扇、三角条带或环,如下所示。 所有多面体都将…

Python turtle库实现基本剖析

有关turtle的相关使用请参考《python图形绘制库turtle中文开发文档及示例大全》 本篇文为turtle库的实现剖析,但不涉及 python 的 TK库。 开始 入口探寻 在turtle中,直走是使用 forward 或者 fd 函数;在本机安装好了 turtle 库后&#xf…

分享我做Dotnet9博客网站时积累的一些资料

从2019年使用WordPress搭建Dotnet9网站,到现在手撸代码开发,介绍中间使用的一些资源,绝无保留,希望对大家有用。1. 申请域名、搭建WordPress网站时间点:2019年11月申请Dotnet9域名,讲个实话,站长…

基于Azure Blob冷存储的数据压缩备份总结

基于上一篇的压缩算法对比分析报告,选择了LZ4算法的普通模式,其测试压缩率为28%,20G压缩时间为256s,估计1T的冷备时间为3.5h。 接下来,将23T的HBase历史数据进行了压缩冷备,压缩后大小为3.5T,冷…

Ubuntu使用VNC运行基于Docker的桌面系统

2019独角兽企业重金招聘Python工程师标准>>> docker-ubuntu-vnc-desktop From Docker Index docker pull dorowu/ubuntu-desktop-lxde-vnc Build yourself git clone https://github.com/fcwu/docker-ubuntu-vnc-desktop.git docker build --rm -t dorowu/ubuntu-de…

【ArcGIS风暴】ArcGIS个人数据库(.mdb)中矢量字段(如Shape_Length、Shape_Area)无法删除的解决办法

ArcGIS中,某些操作,比如空间连接(Spatial Join)结果属性表中会自动产生Shape_Length和Shape_Area字段,这些字段无法删除,如下: 即使在工具箱中的【删除字段】工具,也找不到这些字段,如图所示,给我们的数据入库工作带来了一定的困扰。 解决思路: mdb是个人数据库,基…

python thinker canvas create_arc 使用详解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/A757291228/article/details/106739556 ———————————————— 版权声明:本文…

剑指offer之二叉搜索树和双向链表

1 问题 比如我们搜索二叉树如下,我们需要变成双向链表 2 分析 我们知道这个变成双向链接的时候是按照树的中序遍历打印的,我们只需要在中序遍历打印的时候操作该节点,我们可以用临时变量保存这个节点,同时我们也需要单独增加一…

text 热敏打印机_只要有想象力,打印机都能做游戏

不知道为什么,文本冒险游戏最近频频被人提及。这不,现在又出来一个基于实时打印的文本冒险游戏 —— Quest Smith。这位脑洞较大的创客名叫 Bekir Dağ ,他用微型打印机和树莓派做出了这个手持游戏设备。关于文本冒险游戏的背景知识&#xff…

C#内建接口:IConvertible

这节来讲一个比较有意思的接口:IConvertible。IConvertible接口处于System.Runtime命名空间下,这个接口规定了一批ToXxx()方法,凡是实现了这个接口的方法,我们都可以尝试将其转换为自己想要的类型。IConvertible中有什么&#xff…

ArcGIS升级地理数据库

本博文教大家如何快速地将低版本地理数据库升级为高版本地理数据库。 方法一:使用“升级地理数据库”工具箱二、使用ArcCatalog地理数据库→右键→属性。三、创建不同版本的地理数据库

汉高软件服务器安装系统,如何安装了如指掌眼镜管理系统的服务器和客户端,还需要安装什么软件的?...

满意答案ven85202014.05.09采纳率:53% 等级:7已帮助:356人易软眼镜店管理系统它整合了整个眼镜店的收费、客户登记、验光单管理、配镜管理、财务管理和查旬报表以及库存管理一体化的管理系统。随时可以查看客户的验光单、对比,…

Python3 实现单例设计模式

单例模式的一般实现 饿汉式 懒汉式就是通过一个方法才能实现单例,我不是很常用,所以在此就写个饿汉式。以后再补懒汉式。 单例模式的核心作用是保证一个类只有一个该类型的对象。在一个对象被过多调用时避免过多的消耗内存,即可使用单例模式…

基于casbin的ABAC/RBAC权限实践

五一假期疫情封在家也没事做,就想来优化一下一个前端容器小项目之前的TODOlist里面有一项是权限这块时隔2年了还一直没有动手迟迟没搞主要还是我太懒了,哈哈 其实我一直想要找一个轻量级的权限通用方案权限的数据源可以切换,但是逻辑基本不用…