Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ede64ed

Browse files
committed
1
1 parent 2c36fd1 commit ede64ed

File tree

10 files changed

+295
-15
lines changed

10 files changed

+295
-15
lines changed
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

‎ByteEdu.Com斗兽棋全栈课程/课程代码/server/ByteEdu_DSQ/src/DSQ_server/HandleClt.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ func (this *DSQGame) HandleCltProtocol2(protocol2 interface{}, ProtocolData map[
2828
MapSafe: M,
2929
}
3030
switch protocol2 {
31+
case float64(Proto_DSQGame.C2G_Player_PiPeiGame_Proto):
32+
{
33+
ConnectionData.PlayerPiPei(ProtocolData)
34+
}
3135
case float64(Proto_DSQGame.C2G_Player_Login_Proto):
3236
{
3337
ConnectionData.PlayerLogin(ProtocolData)

‎ByteEdu.Com斗兽棋全栈课程/课程代码/server/ByteEdu_DSQ/src/DSQ_server/HandleCltFunc.go‎

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,32 @@ package main
33
import (
44
"DSQ_login/Proto"
55
// "DSQ_server/Player"
6+
"DSQ_server/Match"
67
"DSQ_server/Proto"
78
"LollipopGo/LollipopGo/network"
89
"encoding/json"
910
"fmt"
1011
)
1112

12-
/*
13+
// 玩家匹配
14+
func (this *DSQGame) PlayerPiPei(ProtocolData map[string]interface{}) {
15+
fmt.Println("PlayerPiPei-------------------", ProtocolData)
16+
strOpenID := ProtocolData["OpenID"].(string)
1317

14-
type PlayerData struct {
15-
UID int // 玩家UID
16-
OpenID string // MD5 字符串
17-
Name string // 玩家名字
18-
Avatar string // 玩家头像
19-
Level int // 玩家等级
20-
Coin int64 // 玩家金币
21-
// ... ...
18+
// 匹配逻辑
19+
// 1. 队列形式-- chan
20+
// 2. 匹配成功
21+
val, err := this.MapSafe.Get(strOpenID + "|User")
22+
if err != nil {
23+
fmt.Println(err)
24+
return
25+
}
26+
fmt.Println("--------------------val:", val)
27+
DSQ_match.PutMatchList(val.(*DSQGame).Player)
28+
return
2229
}
2330

24-
25-
*/
26-
31+
// 玩家登录
2732
func (this *DSQGame) PlayerLogin(ProtocolData map[string]interface{}) {
2833
fmt.Println("PlayerLogin-------------------", ProtocolData)
2934
strtoken := ProtocolData["Tocken"].(string)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package DSQ_match
2+
3+
import (
4+
"DSQ_server/Player"
5+
"time"
6+
)
7+
8+
/*
9+
如何解决 匹配高并发下的panic问题(第二期解决)
10+
*/
11+
12+
var (
13+
GMatchChan chan map[string]*Player_DSQ.PlayerData
14+
Gmap map[string]*Player_DSQ.PlayerData
15+
)
16+
17+
func init() {
18+
GMatchChan = make(chan map[string]*Player_DSQ.PlayerData, 1000)
19+
Gmap = make(map[string]*Player_DSQ.PlayerData)
20+
go Timer()
21+
}
22+
23+
// 玩家的数据匹配压入
24+
func PutMatchList(data *Player_DSQ.PlayerData) {
25+
Gmap[data.OpenID] = data
26+
}
27+
28+
// 匹配timer
29+
func Timer() {
30+
for {
31+
select {
32+
case <-time.After(time.Millisecond * 1):
33+
{
34+
// 进行数据验证 -- 确保我们链接信息完全获取到
35+
// ???? 不够严谨,如果不验证玩家数据是否保存成功,会导致客户端一个匹配成功,无法游戏。
36+
// 确保2个人, 如果满足len(Gmap)%2 == 0 ---> GMatchChan
37+
if len(Gmap)%2 == 0 && len(Gmap) != 0 {
38+
datatmp := make(map[string]*Player_DSQ.PlayerData)
39+
for k, v := range Gmap {
40+
datatmp[k] = v
41+
delete(Gmap, k)
42+
}
43+
SendGMatchChan(datatmp)
44+
}
45+
}
46+
}
47+
}
48+
}
49+
50+
// 压如匹配函数
51+
func SendGMatchChan(data map[string]*Player_DSQ.PlayerData) {
52+
if len(data) == 0 {
53+
return
54+
}
55+
GMatchChan <- data
56+
}

‎ByteEdu.Com斗兽棋全栈课程/课程代码/server/ByteEdu_DSQ/src/DSQ_server/Proto/Proto2.go‎

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ package Proto_DSQGame
22

33
import (
44
"DSQ_server/Player"
5+
"DSQ_server/ST"
56
)
67

78
// 主协议 10号
89
const (
9-
DSQGameINIT = iota // 初始化操作
10-
C2G_Player_Login_Proto // C2G_Player_Login_Proto == 1 客户端到游戏服务器验证
11-
G2C_Player_Login_Proto // G2C_Player_Login_Proto == 2 服务器返回 是否成功
10+
DSQGameINIT = iota // 初始化操作
11+
C2G_Player_Login_Proto // C2G_Player_Login_Proto == 1 客户端到游戏服务器验证
12+
G2C_Player_Login_Proto // G2C_Player_Login_Proto == 2 服务器返回 是否成功
13+
C2G_Player_PiPeiGame_Proto // C2G_Player_PiPeiGame_Proto == 3 客户端到游戏服务器 玩家匹配
14+
Broadcast_PiPeiGame_Proto // Broadcast_PiPeiGame_Proto == 4 服务器返回 是否成功,广播协议
1215
)
1316

1417
// 斗兽棋的枚举
@@ -24,6 +27,22 @@ const (
2427
Mouse // 老鼠 ==8
2528
)
2629

30+
// -----------------------------------------------------------------------------
31+
// C2G_Player_PiPeiGame_Proto == 3 客户端到游戏服务器 玩家匹配
32+
type C2G_Player_PiPeiGame struct {
33+
Protocol int
34+
Protocol2 int
35+
OpenID string // 玩家的唯一ID
36+
}
37+
38+
// Broadcast_PiPeiGame_Proto == 4 服务器返回 是否成功
39+
type Broadcast_PiPeiGame struct {
40+
Protocol int
41+
Protocol2 int
42+
Bsucc bool // true :匹配成功, false:匹配失败
43+
RoomData *DSQ_ST.RoomData // 房间信息,房间的ID,匹配成功的玩家的数据,当前的牌桌上的数据(双方的信息,倒计时等)
44+
}
45+
2746
// -----------------------------------------------------------------------------
2847
// G2C_Player_Login_Proto == 2 客户端到游戏服务器验证
2948
type G2C_Player_Login struct {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package DSQ_ST
2+
3+
import (
4+
"DSQ_server/Player"
5+
)
6+
7+
// 座位信息
8+
type SeatDataST struct {
9+
SeatID int // 默认的 0,1
10+
PlayerData *Player_DSQ.PlayerData
11+
LeftTime int
12+
// 不需要发送初始化棋盘数据,
13+
}
14+
15+
/*
16+
匹配成功后的房间信息
17+
1. roomid 例如:从1000开始
18+
2. 玩家的数据
19+
3. 牌桌的数据
20+
*/
21+
type RoomData struct {
22+
RoomID int // 房间if=d
23+
RoomName string // 非必要的
24+
SeatData [2]*SeatDataST // 座位信息,默认规则 0号位置默认是 红方,1号位置默认是 蓝方
25+
TurnID int // 轮到谁,防止:玩家多操作
26+
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package main
2+
3+
import (
4+
"DSQ_server/Match"
5+
"DSQ_server/Proto"
6+
"DSQ_server/ST"
7+
"fmt"
8+
"strconv"
9+
"sync"
10+
"time"
11+
)
12+
13+
var (
14+
// GRoomManager map[string]*GRoomSTData // 其中一种
15+
GRoomManagerPtr *GRoomSTData // 彬哥推荐
16+
GRoomID int
17+
)
18+
19+
/*
20+
1. 肯定联系到我们的之前设计的房间结构:RoomData
21+
2. 并发安全问题
22+
*/
23+
24+
type GRoomSTData struct {
25+
GRoomData map[string]*DSQ_ST.RoomData
26+
RoomLock *sync.RWMutex
27+
}
28+
29+
func init() {
30+
// GRoomManager = make(map[string]*GRoomSTData)
31+
GRoomManagerPtr = NewGRoomManagerPtr()
32+
GRoomID = 1000
33+
go MatchTimer() // 全局的定时器,出现panic 或者中断,整个匹配机制就无法继续进行了。
34+
}
35+
36+
func NewGRoomManagerPtr() *GRoomSTData {
37+
return &GRoomSTData{
38+
GRoomData: make(map[string]*DSQ_ST.RoomData),
39+
RoomLock: new(sync.RWMutex),
40+
}
41+
}
42+
43+
/*
44+
获取RoomID长度
45+
每一个匹配成功的数据的总和,例如: A,B ---> {A,B} len(GRoomData) == 1 ,C,D ---> {C,D} len(GRoomData)+1
46+
1. 读写锁的使用
47+
2. 获取全局的RoomID
48+
*/
49+
func GetGRoomDataLen() int {
50+
GRoomManagerPtr.RoomLock.RLock()
51+
ilen := len(GRoomManagerPtr.GRoomData) + GRoomID
52+
GRoomManagerPtr.RoomLock.RUnlock()
53+
return ilen
54+
}
55+
56+
/*
57+
说明:1. 2人组合一个房间。
58+
2. 发送广播消息(Broadcast_PiPeiGame_Proto)
59+
3. 房间生成规则
60+
4. 处理数据结构,go 与我们住进程 -- 线程通信方式:Go 通过通信来实现共享内存
61+
*/
62+
63+
func MatchTimer() {
64+
startTumer := time.NewTicker(time.Millisecond * 10)
65+
for {
66+
select {
67+
case <-startTumer.C:
68+
{ // 存的数据结构:map[string]*Player_DSQ.PlayerData
69+
// len(Gmap)%2 == 0 && len(Gmap) != 0
70+
datachan := <-DSQ_match.GMatchChan
71+
openida, openidb := "", ""
72+
for kc, _ := range datachan {
73+
if len(openida) == 0 {
74+
openida = kc
75+
} else {
76+
openidb = kc
77+
}
78+
}
79+
for _, v := range datachan {
80+
_ = v
81+
// 2个人匹配成功 ---> 去创建房间 (房间的创建规则?) --- 逻辑思维
82+
// 玩家的广播链接信息,我们如何取?--- 看听课认真不
83+
// this.MapSafe.Put(STsend.PlayerData.OpenID+"|User", onlineUser)
84+
// 1. Get方法去取数据 --
85+
// 2. 循环我们这个数据结构, for k,v :=range M -- 1W
86+
vala, _ := M.Get(openida + "|User")
87+
valb, _ := M.Get(openidb + "|User")
88+
89+
/*
90+
1. 通过roomid获取获取roomData数据
91+
2. 判断roomdata下面的seatdata数据是否2个玩家都有数据
92+
3. 如果 第2步骤seatdata 已经全部有数据,以第1步骤的roomid创建房间信息
93+
4. 否则继续循环数据,添加到 roomdata成员变量seatdata
94+
*/
95+
GRoomManagerPtr.RoomLock.RLock()
96+
roomdatatmp := GRoomManagerPtr.GRoomData[strconv.Itoa(GetGRoomDataLen())]
97+
GRoomManagerPtr.RoomLock.RUnlock()
98+
if roomdatatmp == nil {
99+
roomdatatmp = &DSQ_ST.RoomData{}
100+
}
101+
/* seatData的数据结构
102+
1. 2个玩家
103+
2. 每个玩家的棋牌初始化数据,4*4 服务器的棋盘初始化操作--保存到server内存数据中的
104+
type SeatDataST struct {
105+
SeatID int // 默认的 0,1
106+
PlayerData *Player_DSQ.PlayerData
107+
LeftTime int
108+
}
109+
*/
110+
seatdataa := &DSQ_ST.SeatDataST{
111+
SeatID: 0,
112+
PlayerData: vala.(*DSQGame).Player,
113+
LeftTime: 20,
114+
}
115+
116+
seatdatab := &DSQ_ST.SeatDataST{
117+
SeatID: 1,
118+
PlayerData: valb.(*DSQGame).Player,
119+
LeftTime: 20,
120+
}
121+
122+
roomdatatmp.SeatData[0] = seatdataa
123+
roomdatatmp.SeatData[1] = seatdatab
124+
125+
/*
126+
val 是什么数据 -->
127+
type DSQGame struct {
128+
Connection *websocket.Conn
129+
StrMD5 string // 唯一ID
130+
MapSafe *concurrent.ConcurrentMap
131+
Player *Player_DSQ.PlayerData
132+
}
133+
134+
// Broadcast_PiPeiGame_Proto == 4 服务器返回 是否成功
135+
type Broadcast_PiPeiGame struct {
136+
Protocol int
137+
Protocol2 int
138+
Bsucc bool // true :匹配成功, false:匹配失败
139+
RoomData *DSQ_ST.RoomData // 房间信息,房间的ID,匹配成功的玩家的数据,当前的牌桌上的数据(双方的信息,倒计时等)
140+
}
141+
*/
142+
// 发消息,通知玩家匹配成功了
143+
data := Proto_DSQGame.Broadcast_PiPeiGame{
144+
Protocol: 10,
145+
Protocol2: 4,
146+
Bsucc: true,
147+
}
148+
149+
/* 房间的数据结构
150+
1. 服务器的房间的manager
151+
2. 管理房间的数据结构,包括:玩家的数据(红方,蓝方),房间的GC(timer)
152+
3. 玩家的数据的游戏数据存储,包括(玩家的报名,玩家的结算数据)
153+
4. 自学习的数据收集,包括(玩家的行为,大数据的记录,4*4 ,先手玩家最先点那个牌)
154+
type RoomData struct {
155+
RoomID int // 房间if=d
156+
RoomName string // 非必要的
157+
SeatData [2]*SeatDataST // 座位信息,默认规则 0号位置默认是 红方,1号位置默认是 蓝方
158+
TurnID int // 轮到谁,防止:玩家多操作
159+
}
160+
*/
161+
data.RoomData = roomdatatmp
162+
fmt.Println(data)
163+
vala.(*DSQGame).PlayerSendMessage(data)
164+
valb.(*DSQGame).PlayerSendMessage(data)
165+
break
166+
}
167+
}
168+
}
169+
}
170+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /