免费国产精品自在自线-91精品国产色综合久久久浪潮-99热久久免费频精品-国产精品国模在线观看-久久亚洲国产精品成人?V秋霞-久久国产一级A片免费播放-亚洲国产欧洲综合97久久-久久国产白嫩美女呻吟高潮

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線(xiàn)實(shí)戰(zhàn)洞察。

基于ET框架的斗地主Demo開(kāi)發(fā)實(shí)踐與踩坑指南

基于ET框架的斗地主Demo開(kāi)發(fā)實(shí)踐與踩坑指南 簡(jiǎn)介基于ET框架的斗地主Demo是一份面向游戲開(kāi)發(fā)初學(xué)者的ET框架實(shí)踐示例旨在幫助快速掌握ET4.0版本的核心用法。資源包共10487個(gè)文件以C#腳本、meta、info、bin、dll、xml及png等類(lèi)型為主涵蓋服務(wù)器端代碼、Unity客戶(hù)端工程、Proto協(xié)議定義、編譯輸出與構(gòu)建產(chǎn)物整體約81.99MB壓縮包為7z格式。通過(guò)本地.bat和使用說(shuō)明.txt可以快速運(yùn)行項(xiàng)目結(jié)合Output、Build等目錄還能了解編譯與打包流程。已有1132人下載學(xué)習(xí)。該Demo不僅展示了ET框架的分布式架構(gòu)、高性能網(wǎng)絡(luò)庫(kù)與熱更新機(jī)制還提供了完整的斗地主玩法代碼。其中Server目錄適合研究游戲邏輯與網(wǎng)絡(luò)處理Unity目錄用于客戶(hù)端界面開(kāi)發(fā)Proto目錄幫助理解協(xié)議定義。通過(guò)該Demo新手可以快速了解ET框架的整體結(jié)構(gòu)掌握服務(wù)器與客戶(hù)端代碼的組織方式理解網(wǎng)絡(luò)通信與熱更新流程并熟悉Unity中游戲界面的設(shè)計(jì)思路。代碼結(jié)構(gòu)清晰對(duì)于希望從零搭建ET框架項(xiàng)目的開(kāi)發(fā)者這份Demo提供了可直接運(yùn)行的參考是理論與實(shí)踐結(jié)合的入門(mén)佳選。1. 基于ET框架的斗地主Demo先跑通一桌牌再談框架選型斗地主這種牌局在牌類(lèi)項(xiàng)目里屬于“看著簡(jiǎn)單、寫(xiě)起來(lái)全是細(xì)節(jié)”的活兒54張牌的組合判斷、叫地主的三分制、順子炸彈的壓牌規(guī)則任何一條沒(méi)定義清楚對(duì)局就會(huì)在第三輪出牌時(shí)突然翻車(chē)?;贓T框架的斗地主Demo就是把ET框架這套以實(shí)體組件為核心、自帶消息分發(fā)和服務(wù)端熱更的C#游戲框架用來(lái)做一桌能完整跑起來(lái)的斗地主牌局。它的價(jià)值在于驗(yàn)證房間類(lèi)游戲最關(guān)鍵的三件事消息觸發(fā)房間狀態(tài)流轉(zhuǎn)是否順滑、服務(wù)端熱更能不能支撐牌局邏輯快速迭代、多人同時(shí)出牌時(shí)狀態(tài)是否一致。這篇筆記適合第一次碰ET框架、又想以牌局練手的開(kāi)發(fā)者也適合客戶(hù)端程序員想順著Demo理解服務(wù)端消息鏈路、真實(shí)跑通一次。下面按框架原理、本地環(huán)境、核心邏輯、避坑、驗(yàn)證來(lái)展開(kāi)。2. ET框架的分層架構(gòu)與消息流轉(zhuǎn)斗地主Demo為什么適合這樣搭在寫(xiě)任何代碼之前先把ET框架里“實(shí)體、組件、事件、消息”四個(gè)概念和斗地主的對(duì)應(yīng)關(guān)系理清楚。很多人在ET上做第一個(gè)項(xiàng)目時(shí)容易把服務(wù)端寫(xiě)成一堆靜態(tài)類(lèi)加單例那等于繞開(kāi)了框架的核心價(jià)值后面做房間管理和熱更都會(huì)很別扭。2.1 實(shí)體-組件與事件系統(tǒng)框架的“骨”和“筋”ET框架里最基礎(chǔ)的單位是Entity它不是一個(gè)具體的業(yè)務(wù)對(duì)象而是一個(gè)空殼。數(shù)據(jù)住在Component里邏輯寫(xiě)在System或者Handler里。對(duì)應(yīng)到斗地主Demo一張桌子、一個(gè)玩家、一場(chǎng)對(duì)局都是Entity桌面上的公共狀態(tài)和某個(gè)玩家的私有手牌則分別是不同的Component。常見(jiàn)做法是這樣定義兩塊數(shù)據(jù)// Model層只放數(shù)據(jù)定義不寫(xiě)玩法邏輯 public class DeskComponent : Entity { public int RoomId; public int CurrentSeat; // 當(dāng)前操作座位 public int LandlordSeat -1; // 地主座位-1表示還沒(méi)叫完 public int BidScore; // 當(dāng)前最高叫分 public int MaxBidSeat -1; // 當(dāng)前最高分的座位 public Listint DeckCards new(); // 三張底牌 public Listint LastCards new(); // 上一手打出的牌 public int LastPlaySeat -1; // 上一手出牌人 } public class PlayerComponent : Entity { public int SeatIndex; public Listint HandCards new(); public bool IsLandlord; public bool IsOnline; }把RoomId、CurrentSeat這些字段放在DeskComponent里是因?yàn)樗鼈兪侨齻€(gè)玩家共享的狀態(tài)任何一個(gè)人出牌都會(huì)改變CurrentSeat而HandCards只屬于單個(gè)玩家拆開(kāi)放更合理。ET 6.0之后統(tǒng)一了實(shí)體和組件的繼承關(guān)系都叫Entity用AddComponent掛載即可所以上面兩個(gè)類(lèi)直接繼承Entity也沒(méi)有問(wèn)題按你用的分支來(lái)。事件系統(tǒng)則是用來(lái)解耦的。比如玩家進(jìn)入桌子后要觸發(fā)“通知其他玩家”、“推送手牌”、“記錄日志”三件事如果用同步調(diào)用寫(xiě)在一起后面每加一個(gè)動(dòng)作都要?jiǎng)釉镜姆椒?。我一般?huì)用ET的事件發(fā)布來(lái)解耦// 事件定義只攜帶上下文 public struct PlayerEnterDeskEvent { public DeskComponent Desk; public PlayerComponent Player; } // 在進(jìn)入房間的Handler里發(fā)布 await EventSystem.PublishAsync(new PlayerEnterDeskEvent { Desk desk, Player player });訂閱方各自處理自己關(guān)心的事別人訂閱不訂閱互不影響。對(duì)斗地主這種回合明確、事件種類(lèi)少的項(xiàng)目事件系統(tǒng)能讓你把“出牌”和“出牌之后的推送”拆開(kāi)調(diào)試時(shí)只盯一個(gè)環(huán)節(jié)。2.2 一條出牌消息的完整旅程從客戶(hù)端按鈕到服務(wù)端廣播斗地主Demo里最典型的鏈路是出牌??蛻?hù)端三個(gè)玩家其中一個(gè)點(diǎn)擊“出牌”選了幾張牌點(diǎn)確定之后發(fā)生的事情可以拆成六個(gè)步驟??蛻?hù)端構(gòu)造消息并發(fā)送// 客戶(hù)端把選中的牌封裝成消息 var request new C2G_PlayCard { RoomId 1001, Cards selectedCards.ToList() // Listint牌ID列表 }; var response (G2C_PlayCard)await session.Call(request);這里我故意用Call而不是Send。ET框架里Send是只發(fā)不等回復(fù)適合不關(guān)心結(jié)果的廣播Call是請(qǐng)求-響應(yīng)模型會(huì)等待服務(wù)端返回。出牌這個(gè)動(dòng)作必須知道服務(wù)端是否認(rèn)可因?yàn)榉?wù)端要校驗(yàn)牌型、校驗(yàn)是否輪到自己校驗(yàn)失敗客戶(hù)端要立刻回滾手牌狀態(tài)。服務(wù)端收到消息后消息分發(fā)器會(huì)根據(jù)消息Opcode找到對(duì)應(yīng)的Handler[MessageHandler] public class C2G_PlayCardHandler : AMHandlerC2G_PlayCard { protected override async ETTask Run(Session session, C2G_PlayCard message) { // 從Session上取玩家信息這是Gate層綁好的 var user session.GetComponentSessionUserComponent(); if (user null) { session.Send(new G2C_PlayCard { Error ErrorCode.ERR_NeedLogin }); return; } // 通過(guò)玩家ID找到所在房間 var room RoomManagerComponent.Instance.GetRoom(user.PlayerId); if (room null) { session.Send(new G2C_PlayCard { Error ErrorCode.ERR_RoomNotExist }); return; } var desk room.GetComponentDeskComponent(); var result CardLogic.TryPlay(desk, user.PlayerId, message.Cards); // 廣播給其他玩家 if (result.Success) { var broadcast new S2C_PlayCard { SeatIndex result.SeatIndex, Cards message.Cards, RemainCount result.RemainCount }; room.Broadcast(broadcast); } else { session.Send(new G2C_PlayCard { Error result.ErrorCode }); } } }這段Handler體現(xiàn)了ET框架兩個(gè)特點(diǎn)一是Session作為連接載體可以在上面掛用戶(hù)信息組件二是業(yè)務(wù)邏輯不寫(xiě)在Handler里而是放在CardLogic這種靜態(tài)工具類(lèi)或房間實(shí)體的System里Handler只負(fù)責(zé)消息路由和響應(yīng)。這樣熱更時(shí)只換邏輯DLL消息定義和實(shí)體定義不動(dòng)。2.3 選ET還是原生Socket/Mirror三組對(duì)比很多第一次做牌局項(xiàng)目的人會(huì)問(wèn)不用ET用原生Socket加JSON協(xié)議行不行或者用Mirror這種Unity同步庫(kù)行不行我直接給結(jié)論都能做但后期成本不一樣。方案服務(wù)端承載熱更能力消息分發(fā)適合場(chǎng)景原生Socket 自寫(xiě)路由自己實(shí)現(xiàn)線(xiàn)程模型無(wú)自己寫(xiě)教學(xué)、初級(jí)DemoMirror / UNET主從同步為主弱組件同步合作類(lèi)、小規(guī)模聯(lián)機(jī)ET框架多進(jìn)程分布式支持Hotfix熱更Handler Opcode房間類(lèi)、MMO、牌局原生Socket做斗地主要處理的粘包拆包、心跳、重連、消息序號(hào)每一項(xiàng)都需要自己寫(xiě)寫(xiě)三個(gè)月后你得到的只是一個(gè)能跑通的通信庫(kù)牌局邏輯還沒(méi)開(kāi)始。用Mirror這類(lèi)同步庫(kù)它擅長(zhǎng)的Transform同步在牌局里用處不大斗地主是低頻消息、高頻狀態(tài)校驗(yàn)消息同步比狀態(tài)同步更可控。ET框架的好處是消息系統(tǒng)、Actor模型、熱更框架都已經(jīng)是現(xiàn)成的你把注意力放在牌局規(guī)則上就行。這不是玄學(xué)而是成本賬。Demo階段也許感覺(jué)不明顯等你開(kāi)始加機(jī)器人、加錄像回放、加好友圍觀時(shí)ET的消息分發(fā)和組件化拆分優(yōu)勢(shì)就開(kāi)始體現(xiàn)了。3. 用ET框架在本地跑通斗地主Demo環(huán)境準(zhǔn)備與最小房間理解了架構(gòu)之后下一步是讓Demo在本地跑起來(lái)。這一章的每一步都對(duì)應(yīng)一個(gè)命令行或代碼動(dòng)作按順序執(zhí)行完你應(yīng)該能看到一個(gè)空房間被創(chuàng)建然后一個(gè)玩家加進(jìn)去。3.1 準(zhǔn)備工程和啟動(dòng)服務(wù)端Unity項(xiàng)目、.NET工程與進(jìn)程參數(shù)ET框架的服務(wù)端是.NET控制臺(tái)工程客戶(hù)端是Unity工程兩者共用Model和Hotfix代碼。先從官方倉(cāng)庫(kù)拉取代碼切到和你Unity版本匹配的分支git clone ET框架官方倉(cāng)庫(kù)地址 ET cd ET git checkout 6.0 # 按你的Unity版本選擇分支 dotnet build Server/Server.sln構(gòu)建成功后服務(wù)端按進(jìn)程啟動(dòng)。ET框架默認(rèn)有一套多進(jìn)程配置我一般把Realm、Gate、Map拆開(kāi)跑方便定位問(wèn)題# 終端1負(fù)責(zé)登錄驗(yàn)證 dotnet run --project Server/Apps/Server.App -- --AppTypeRealm --Process1 # 終端2負(fù)責(zé)客戶(hù)端連接和轉(zhuǎn)發(fā) dotnet run --project Server/Apps/Server.App -- --AppTypeGate --Process1 # 終端3負(fù)責(zé)房間和牌局邏輯 dotnet run --project Server/Apps/Server.App -- --AppTypeMap --Process1這三個(gè)進(jìn)程參數(shù)里AppType決定了這個(gè)進(jìn)程扮演的角色。Realm管賬號(hào)登錄Gate管客戶(hù)端連接Map管房間邏輯。斗地主Demo的牌桌就創(chuàng)建在Map進(jìn)程上。有的分支支持用--AppTypeAll單進(jìn)程啟動(dòng)適合本地快速調(diào)試但我不建議一開(kāi)始就用因?yàn)槟憧床坏矫總€(gè)進(jìn)程的日志邊界。然后打開(kāi)Unity工程找到Init場(chǎng)景。ET框架的Init場(chǎng)景一般會(huì)有一個(gè)InitComponent里面配置服務(wù)器IP和端口。把這些指到本機(jī)端口和Gate進(jìn)程監(jiān)聽(tīng)的一致。運(yùn)行Unity工程看到“連接成功”日志后服務(wù)端與客戶(hù)端鏈路就通了。3.2 創(chuàng)建房間與加入用一條Call消息打通客戶(hù)端到服務(wù)端鏈路通了之后第一個(gè)功能是創(chuàng)建房間。客戶(hù)端點(diǎn)按鈕發(fā)一條創(chuàng)建房間請(qǐng)求服務(wù)端創(chuàng)建一個(gè)Room實(shí)體并掛上DeskComponent然后返回房間號(hào)[MessageHandler] public class C2G_CreateRoomHandler : AMHandlerC2G_CreateRoom { protected override async ETTask Run(Session session, C2G_CreateRoom message) { var user session.GetComponentSessionUserComponent(); if (user null) { session.Send(new G2C_CreateRoom { Error ErrorCode.ERR_NeedLogin }); return; } // 在Map場(chǎng)景下創(chuàng)建房間實(shí)體 var room EntityFactory.CreateRoomEntity(Game.Scene); room.AddComponentDeskComponent(); // 創(chuàng)建者默認(rèn)坐在0號(hào)位 var player room.AddComponentPlayerComponent(); player.SeatIndex 0; player.HandCards.Clear(); player.IsOnline true; // 返回房間號(hào)給客戶(hù)端 session.Send(new G2C_CreateRoom { RoomId room.Id, Error ErrorCode.ERR_Success }); Log.Info($房間創(chuàng)建成功: {room.Id}); } }這里注意RoomEntity和PlayerComponent都創(chuàng)建在Game.Scene下RoomEntity作為房間的根實(shí)體DeskComponent和玩家組件都掛在這棵實(shí)體樹(shù)上。這樣房間銷(xiāo)毀時(shí)所有子組件一起釋放不會(huì)留下孤兒實(shí)體。客戶(hù)端收到房間號(hào)后可以把UI切到牌桌場(chǎng)景等待其他玩家加入。為了讓調(diào)試更直觀我一般會(huì)在服務(wù)端加一個(gè)模擬加入的接口方便單人調(diào)試// 調(diào)試接口讓一個(gè)假玩家加入房間 [MessageHandler] public class C2G_DebugJoinRoomHandler : AMHandlerC2G_DebugJoinRoom { protected override async ETTask Run(Session session, C2G_DebugJoinRoom message) { var room RoomManagerComponent.Instance.GetRoom(message.RoomId); var player room.AddComponentPlayerComponent(); player.SeatIndex room.GetComponentDeskComponent().NextSeatIndex(); player.IsOnline false; room.Broadcast(new S2C_PlayerEnter { SeatIndex player.SeatIndex }); } }加入房間的邏輯和創(chuàng)建基本一致只是要把玩家角色放到RoomEntity下同時(shí)更新DeskComponent里的座位狀態(tài)。ET框架里座位管理就是一個(gè)簡(jiǎn)單的整數(shù)輪轉(zhuǎn)public int NextSeatIndex() { // 找第一個(gè)空的座位 var desk this.GetComponentDeskComponent(); for (int i 0; i 3; i) { if (!desk.SeatOccupied.ContainsKey(i)) { desk.SeatOccupied[i] true; return i; } } return -1; // 房間滿(mǎn)了 }3.3 自測(cè)與日志如何判斷鏈路真的通了跑Demo最怕的是“看起來(lái)啥都沒(méi)發(fā)生”。我一般通過(guò)三條日志確認(rèn)鏈路第一服務(wù)端Gate進(jìn)程出現(xiàn)“客戶(hù)端連接成功”的日志說(shuō)明TCP連接建立了。第二客戶(hù)端發(fā)起登錄后Realm進(jìn)程出現(xiàn)“驗(yàn)證成功”日志說(shuō)明消息路由到了Realm。第三創(chuàng)建房間后Map進(jìn)程出現(xiàn)“房間創(chuàng)建成功”日志同時(shí)客戶(hù)端界面跳轉(zhuǎn)到了牌桌場(chǎng)景。如果卡在某一步最常見(jiàn)的檢查點(diǎn)消息Opcode是否正確注冊(cè)、客戶(hù)端連接的端口是不是Gate進(jìn)程監(jiān)聽(tīng)的端口、服務(wù)端各個(gè)進(jìn)程是否用了同一個(gè)StartConfig配置。這三項(xiàng)只要有一項(xiàng)不對(duì)消息就不通。4. 斗地主Demo的牌局核心發(fā)牌、叫地主、出牌判斷與回收重置網(wǎng)絡(luò)鏈路跑通后真正的技術(shù)活是牌局邏輯。這一章不講UI只講服務(wù)端的狀態(tài)機(jī)、牌型判斷和校驗(yàn)邏輯。UI只是把服務(wù)端的狀態(tài)渲染出來(lái)。4.1 牌型編碼與發(fā)牌54張牌怎么變成三份手牌和底牌斗地主用54張牌我用整數(shù)做牌ID0到51表示四種花色的3到252是小王53是大王。牌ID只需要唯一性真正比較大小要用“牌面值”也就是3到15對(duì)應(yīng)撲克牌的3到A15是216是小王17是大王。public static class DeckHelper { public const int SMALL_JOKER 52; public const int BIG_JOKER 53; // 生成完整牌堆 public static Listint CreateDeck() { var deck new Listint(54); for (int i 0; i 52; i) deck.Add(i); deck.Add(SMALL_JOKER); deck.Add(BIG_JOKER); return deck; } public static void Shuffle(Listint deck) { var random new Random(); for (int i deck.Count - 1; i 0; i--) { int j random.Next(i 1); (deck[i], deck[j]) (deck[j], deck[i]); } } // 從牌ID取牌面值用于后續(xù)比較 public static int GetCardValue(int cardId) { if (cardId SMALL_JOKER) return 16; if (cardId BIG_JOKER) return 17; return cardId / 4 3; } }發(fā)牌邏輯按座位輪轉(zhuǎn)每人每次拿一張拿17輪最后剩3張做底牌public static void Deal(DeskComponent desk, ListPlayerComponent players) { var deck CreateDeck(); Shuffle(deck); for (int i 0; i 17; i) { for (int p 0; p players.Count; p) { players[p].HandCards.Add(deck[i * players.Count p]); } } // 最后3張是底牌 for (int i 51; i 54; i) { desk.DeckCards.Add(deck[i]); } }這樣發(fā)牌的好處是每個(gè)玩家按輪次各拿一張手牌自然分散避免某個(gè)玩家一口氣拿到一堆大牌導(dǎo)致牌序差異明顯。4.2 叫地主流程用輪轉(zhuǎn)狀態(tài)機(jī)控制三個(gè)玩家的回合叫地主在斗地主里有兩種常見(jiàn)規(guī)則叫分制和搶地主制。Demo階段我建議先實(shí)現(xiàn)叫分制邏輯更清晰。三個(gè)玩家輪流叫1分、2分、3分或者不叫后叫的人必須比當(dāng)前最高分大叫到3分直接結(jié)束三家都不叫就重新發(fā)牌。先把狀態(tài)定義清楚public enum DeskState { None 0, // 等待開(kāi)始 Dealing 1, // 發(fā)牌中 Bidding 2, // 叫地主 Playing 3, // 出牌 Settled 4 // 結(jié)算 }叫地主的流程可以寫(xiě)成一個(gè)純函數(shù)服務(wù)端Handler只負(fù)責(zé)把客戶(hù)端傳來(lái)的叫分交給它public static class BidLogic { public static void OnBid(DeskComponent desk, int seat, int bidScore) { // 非法輸入不是當(dāng)前輪到的人或叫分不大于當(dāng)前最高分 if (seat ! desk.CurrentSeat || bidScore 0 || bidScore 3) { return; } if (bidScore 0) { // 不叫輪到下一個(gè)人 desk.CurrentSeat (desk.CurrentSeat 1) % 3; return; } if (bidScore desk.BidScore) { desk.BidScore bidScore; desk.MaxBidSeat seat; } // 叫到3分或者已經(jīng)輪完一圈結(jié)束叫地主 if (desk.BidScore 3 || IsRoundFinished(desk)) { SetLandlord(desk, desk.MaxBidSeat); } else { desk.CurrentSeat (desk.CurrentSeat 1) % 3; } } private static bool IsRoundFinished(DeskComponent desk) { // 三個(gè)玩家都叫過(guò)或不叫 return desk.LastBidSeat ! -1 (desk.LastBidSeat 1) % 3 desk.CurrentSeat; } private static void SetLandlord(DeskComponent desk, int seat) { desk.LandlordSeat seat; desk.CurrentSeat seat; desk.State DeskState.Playing; // 底牌發(fā)給地主 var player desk.GetPlayer(seat); player.HandCards.AddRange(desk.DeckCards); desk.DeckCards.Clear(); } }這里要注意判斷“本輪結(jié)束”不能光看叫分因?yàn)榭赡艹霈F(xiàn)兩家不叫、一家叫1分的情況還得再輪一次才能確認(rèn)。用LastBidSeat記錄最后一個(gè)叫分的人輪轉(zhuǎn)回來(lái)就結(jié)束更準(zhǔn)確。4.3 出牌合法性判斷牌型識(shí)別與比較函數(shù)出牌判斷是整個(gè)Demo最核心的部分也是新手最容易翻車(chē)的地方。先把牌型枚舉列出來(lái)public enum CardType { None 0, Single 1, // 單張 Pair 2, // 對(duì)子 Three 3, // 三張 ThreeOne 4, // 三帶一 ThreePair 5, // 三帶二 Straight 6, // 順子 StraightPair 7, // 連對(duì) Plane 8, // 飛機(jī)不帶 PlaneSingle 9, // 飛機(jī)帶單 Bomb 10, // 炸彈 Rocket 11 // 王炸 }判斷牌型的核心思路先統(tǒng)計(jì)每種牌面值出現(xiàn)的次數(shù)再根據(jù)次數(shù)分布和數(shù)量判斷public static CardType GetCardType(Listint cards) { if (cards null || cards.Count 0) return CardType.None; int n cards.Count; // 統(tǒng)計(jì)每個(gè)牌面值的張數(shù) var countDict new Dictionaryint, int(); foreach (int id in cards) { int v DeckHelper.GetCardValue(id); countDict[v] countDict.GetValueOrDefault(v) 1; } var values countDict.Keys.OrderBy(x x).ToList(); var groups countDict.Values.OrderBy(x x).ToList(); int distinct values.Count; int maxCount countDict.Values.Max(); if (n 1) return CardType.Single; if (n 2) { // 王炸大小王各一張 if (countDict.ContainsKey(16) countDict.ContainsKey(17)) return CardType.Rocket; if (maxCount 2) return CardType.Pair; return CardType.None; } if (n 3 maxCount 3) return CardType.Three; if (n 4 maxCount 4) return CardType.Bomb; if (n 4 maxCount 3) return CardType.ThreeOne; if (n 5 distinct 2 maxCount 3) return CardType.ThreePair; if (n 5 maxCount 1 values.Max() 15 IsContinuous(values)) return CardType.Straight; if (n 6 maxCount 2 distinct n / 2 values.Max() 15 IsContinuous(values)) return CardType.StraightPair; // 飛機(jī)識(shí)別略按“連續(xù)的三張”數(shù)量判斷 if (n 6 maxCount 3) { var threeValues countDict.Where(kv kv.Value 3).Select(kv kv.Key).OrderBy(x x).ToList(); if (threeValues.Count 2 IsContinuous(threeValues)) return n threeValues.Count * 3 ? CardType.Plane : CardType.PlaneSingle; } return CardType.None; } private static bool IsContinuous(Listint values) { for (int i 1; i values.Count; i) { if (values[i] ! values[i - 1] 1) return false; } return true; }判斷能不能壓過(guò)上家規(guī)則是王炸最大任何炸彈壓過(guò)非炸彈同類(lèi)型牌比主牌大小其他情況不能壓public static bool CanBeat(CardType lastType, int lastMainValue, CardType curType, int curMainValue) { if (curType CardType.Rocket) return true; if (lastType CardType.Rocket) return false; if (curType CardType.Bomb) { if (lastType ! CardType.Bomb) return true; return curMainValue lastMainValue; } if (curType ! lastType) return false; return curMainValue lastMainValue; }這里的主牌值取牌型里最大的牌面值。順子取最大值三帶一取三張的值炸彈取四張的值。這個(gè)函數(shù)寫(xiě)完后要單獨(dú)做一遍完整的測(cè)試后面第6章會(huì)講驗(yàn)證方法。4.4 一局結(jié)束勝負(fù)判定與房間重置一局牌結(jié)束的標(biāo)志是某個(gè)玩家手牌出完。服務(wù)端在每次出牌成功后檢查出牌者剩余手牌數(shù)public static void OnPlayCard(DeskComponent desk, int seat, Listint cards) { var player desk.GetPlayer(seat); // 校驗(yàn)輪次和牌型通過(guò)后從手牌中移除 foreach (int id in cards) { player.HandCards.Remove(id); } desk.LastCards cards; desk.LastPlaySeat seat; if (player.HandCards.Count 0) { // 一局結(jié)束進(jìn)入結(jié)算狀態(tài) desk.State DeskState.Settled; desk.WinnerSeat seat; // 廣播S2C_GameFinish return; } // 下家出牌如果上家出了牌下家必須跟或過(guò) if (desk.PassCount 2) { desk.LastCards null; desk.LastPlaySeat -1; desk.PassCount 0; } desk.CurrentSeat (seat 1) % 3; }結(jié)算后要重置房間。很多Demo在這里偷懶直接把房間銷(xiāo)毀、讓玩家重新建房但這會(huì)給客戶(hù)端帶來(lái)不必要的跳轉(zhuǎn)。我一般是把DeskComponent里的數(shù)據(jù)全部清空保留RoomEntity進(jìn)入“等待下一局”狀態(tài)public static void ResetDesk(DeskComponent desk) { desk.State DeskState.None; desk.LandlordSeat -1; desk.BidScore 0; desk.MaxBidSeat -1; desk.DeckCards.Clear(); desk.LastCards.Clear(); desk.LastPlaySeat -1; desk.CurrentSeat 0; desk.PassCount 0; // 清掉所有玩家的手牌 foreach (var player in desk.GetPlayers()) { player.HandCards.Clear(); player.IsLandlord false; } }重置不等于銷(xiāo)毀這是兩個(gè)概念。銷(xiāo)毀房間會(huì)導(dǎo)致所有玩家斷線(xiàn)重置則讓同一批玩家無(wú)縫開(kāi)始下一局體驗(yàn)完全不同。5. 避坑ET框架寫(xiě)斗地主的5個(gè)典型踩坑記錄這一章記錄的都是在ET框架上做牌局項(xiàng)目最常見(jiàn)的坑。每一條都是“現(xiàn)象、原因、解決”三段式基本覆蓋了從熱更、消息路由到并發(fā)和資源清理的問(wèn)題。5.1 改了Hotfix邏輯卻不生效現(xiàn)象改完出牌判斷邏輯Unity客戶(hù)端重新運(yùn)行服務(wù)端也重啟了但打出的牌還是按舊規(guī)則校驗(yàn)。查代碼發(fā)現(xiàn)新邏輯已經(jīng)在工程里運(yùn)行的就是不對(duì)。原因ET框架的服務(wù)端熱更邏輯編譯后要拷貝到服務(wù)器進(jìn)程目錄很多分支在構(gòu)建時(shí)不會(huì)自動(dòng)同步。Unity側(cè)編輯的是Hotfix工程運(yùn)行的是服務(wù)器目錄下的一份DLL拷貝。兩邊的文件不一致改的是源工程跑的是舊DLL。解決每次改完Hotfix代碼構(gòu)建后確認(rèn)服務(wù)器目錄下的Hotfix.dll時(shí)間戳是否更新。我一般會(huì)寫(xiě)一個(gè)批處理腳本把構(gòu)建產(chǎn)物復(fù)制到服務(wù)器運(yùn)行目錄再啟動(dòng)進(jìn)程。排查時(shí)先看文件時(shí)間再談其他這一步能排除一半的玄學(xué)問(wèn)題。5.2 消息Opcode重復(fù)導(dǎo)致Handler串線(xiàn)現(xiàn)象客戶(hù)端發(fā)的是“出牌”消息服務(wù)端卻執(zhí)行了“叫地主”的Handler。整個(gè)流程沒(méi)報(bào)錯(cuò)但狀態(tài)流轉(zhuǎn)完全不對(duì)。原因ET框架用整型Opcode作為消息的唯一標(biāo)識(shí)新加消息時(shí)如果復(fù)制了已有消息定義忘記改Opcode編號(hào)兩條消息就共用同一個(gè)Opcode。分發(fā)器按Opcode找Handler第一條查到的Handler就被執(zhí)行了。解決給消息編號(hào)按模塊分段比如房間類(lèi)消息從10001開(kāi)始牌局類(lèi)消息從20001開(kāi)始登錄類(lèi)從30001開(kāi)始。新加消息時(shí)先查一遍現(xiàn)有Opcode而不是順眼就復(fù)制。框架本身有一些工具能檢查重復(fù)但我還是建議自己維護(hù)一個(gè)消息清單新消息在清單里登記編號(hào)。5.3 客戶(hù)端和服務(wù)端手牌狀態(tài)不一致現(xiàn)象客戶(hù)端顯示玩家A手上還有5張牌服務(wù)端記錄只有4張。再出幾次兩邊手牌數(shù)量差得越來(lái)越多最終某次出牌被服務(wù)端拒絕玩家卡死。原因客戶(hù)端在發(fā)送出牌請(qǐng)求后立即做了本地手牌移除而沒(méi)有等服務(wù)端確認(rèn)。服務(wù)端校驗(yàn)失敗時(shí)客戶(hù)端沒(méi)有收到失敗回執(zhí)或者收到了但沒(méi)有執(zhí)行回滾。解決客戶(hù)端必須先出牌請(qǐng)求等服務(wù)端返回成功后才更新本地手牌。我在Demo里統(tǒng)一用Call而不是Send服務(wù)端返回成功或失敗客戶(hù)端只信響應(yīng)。這會(huì)有一次RTT的延遲但牌局游戲?qū)O低延遲不敏感一致性?xún)?yōu)先級(jí)更高。5.4 多線(xiàn)程下共用List導(dǎo)致牌序錯(cuò)亂現(xiàn)象服務(wù)端偶爾出現(xiàn)手牌列表里多了一張、少了一張或者出牌順序偶發(fā)混亂。不頻繁但一出現(xiàn)就導(dǎo)致整局無(wú)法繼續(xù)。原因ET框架底層會(huì)起多個(gè)線(xiàn)程處理網(wǎng)絡(luò)消息如果兩個(gè)消息Handler同時(shí)操作同一個(gè)DeskComponent或PlayerComponent里的List就會(huì)產(chǎn)生競(jìng)態(tài)。比如“出牌”和“超時(shí)自動(dòng)出牌”兩個(gè)消息同時(shí)到達(dá)一個(gè)在讀List一個(gè)在Remove。解決共享狀態(tài)統(tǒng)一回主邏輯線(xiàn)程操作。ET框架提供了同步上下文機(jī)制在Handler里用異步調(diào)度把真正修改房間數(shù)據(jù)的代碼切回主線(xiàn)程避免多個(gè)線(xiàn)程交叉訪(fǎng)問(wèn)。具體做法是把實(shí)際邏輯放到Room實(shí)體的System里由房間Actor串行處理消息只是一個(gè)觸發(fā)信號(hào)。Actor模型天然串行處理同一實(shí)體的消息這是ET框架處理房間類(lèi)玩法的標(biāo)準(zhǔn)手段。如果你用裸List當(dāng)共享狀態(tài)又不開(kāi)Actor早晚出問(wèn)題。5.5 房間Actor消息沒(méi)清理現(xiàn)象新開(kāi)的第二局某玩家手牌里出現(xiàn)了上一局的殘牌或者上上局的出牌廣播在新一局開(kāi)始后還在推送。原因房間銷(xiāo)毀或重置時(shí)沒(méi)有移除這個(gè)房間實(shí)體上的消息訂閱也沒(méi)有清理Actor消息隊(duì)列。上一局延遲的消息在新一局開(kāi)始后繼續(xù)投遞到同一個(gè)RoomEntity導(dǎo)致?tīng)顟B(tài)污染。解決房間銷(xiāo)毀前必須做清理調(diào)用RemoveComponent移除牌局組件取消訂閱的事件清空MessageQueue。如果是重置而不是銷(xiāo)毀要保證消息隊(duì)列里的舊消息已經(jīng)全部處理完再執(zhí)行ResetDesk。我現(xiàn)在習(xí)慣在房間Service的OnDestroy里統(tǒng)一做清理而不是散落在各個(gè)Handler里。這個(gè)習(xí)慣比任何調(diào)試技巧都管用。6. 進(jìn)階用對(duì)拍腳本和壓測(cè)驗(yàn)證Demo是否正確Demo能跑通只是第一步證明它總是正確是另一回事。牌局類(lèi)項(xiàng)目最適合用“對(duì)拍”來(lái)驗(yàn)證寫(xiě)一批構(gòu)造的牌型用例跑同一個(gè)判斷函數(shù)輸出有沒(méi)有斷言失敗。這比手動(dòng)點(diǎn)幾十輪牌高效得多。6.1 牌型判斷批量對(duì)拍我在Unity的Editor目錄或者服務(wù)端測(cè)試工程里放一組測(cè)試用例[Test] public void Straight_With_Joker_Should_Be_Invalid() { // 順子帶王應(yīng)該判為非法牌型 var cards new Listint { 0, 1, 2, 3, 52 }; Assert.AreEqual(CardType.None, CardLogic.GetCardType(cards)); } [Test] public void Bomb_Should_Beat_Straight() { var straight new Listint { 8, 9, 10, 11, 12 }; // 6 7 8 9 10 var bomb new Listint { 4, 8, 12, 16 }; // 四張3 Assert.IsTrue(CardLogic.CanBeat( CardLogic.GetCardType(straight), 10, CardLogic.GetCardType(bomb), 3)); }這類(lèi)用例要覆蓋單張、對(duì)子、三帶一、三帶二、順子的邊界5張成立、4張不成立、連對(duì)、飛機(jī)帶單、炸彈壓順子、王炸壓炸彈、2不能進(jìn)順子這八項(xiàng)。每項(xiàng)都算出預(yù)期結(jié)果再斷言跑一遍比人工試一百輪更可靠。我現(xiàn)在接手任何牌局項(xiàng)目第一件事就是把牌型判斷單獨(dú)拎出來(lái)做對(duì)拍哪怕它已經(jīng)跑了很久。6.2 壓測(cè)和日志習(xí)慣網(wǎng)絡(luò)層壓測(cè)不需要復(fù)雜工具寫(xiě)一個(gè)簡(jiǎn)單的并發(fā)循環(huán)就行var tasks new ListETTask(); for (int i 0; i 30; i) { int userId i; tasks.Add(RunPlayer(userId)); } await ETTask.WaitAll(tasks);RunPlayer里模擬登錄、創(chuàng)建房間、加入房間、循環(huán)出牌把每次請(qǐng)求的耗時(shí)打點(diǎn)統(tǒng)計(jì)。30路并發(fā)能讓服務(wù)端消息處理瓶頸暴露出來(lái)比如某個(gè)Handler里做了耗時(shí)的同步操作壓測(cè)日志會(huì)明顯看到響應(yīng)時(shí)間飆升。日志方面我習(xí)慣給每局牌加一個(gè)全局唯一的局號(hào)所有日志打印帶上局號(hào)和座位號(hào)。排查跨局串號(hào)時(shí)按局號(hào)過(guò)濾日志一眼就能定位。6.3 一局結(jié)束后的復(fù)盤(pán)最近一次做類(lèi)似項(xiàng)目我把牌型對(duì)拍腳本、30路壓測(cè)和局號(hào)日志三樣都上了。效果是排查消息串線(xiàn)從“靠猜”變成了“按局號(hào)拉日志”。如果你想把這個(gè)Demo往深了做下一步可以加斷線(xiàn)重連、叫地主超時(shí)自動(dòng)處理、機(jī)器人托管。這些都是很好的進(jìn)階練習(xí)核心牌局邏輯不用動(dòng)。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
久99热在线观看| 蜜乳国产网站| 丁香五月激情月| 九九热视频精品| 激情婷婷丁香色五月| 丁香五月在线自慰| 婷婷五月丁香超碰| 日韩av网站在线观看| 午夜少妇在线观看视频| 色婷婷丁香五月| 久久丁香五月| 亚洲AV中文在线| 成 久久| 91婷婷在线| 91综合色噜噜| 色婷婷综合电影| 久久国产一区二区三区| 大地资源色婷婷视频在线| 日韩成人av在线| 婷婷五月综合激情免费视频| 这里只有精品9| 久久色五月天| 久久亚洲网| 五月停停色色丁香| 任你爽精品免费视频6| 丁香五月婷婷国产av| 337p大胆噜噜噜噜噜91Av| www.99热这里精品| 狠狠干在线| 99热在线精品观看| 亚洲五月花| 99热亚洲精品66| 六月香五月婷| 婷婷丁香五月天中文字幕| 九九国产精视频| 五月天成人综合| 99人妻碰碰碰久久久久视| 我淫我色婷婷五月天激情四射| 成人午夜天| 久久婷婷精品| 中字幕视频在线永久在线观看免费| 伊人99热| 无码日本精品XXXXXXXXX | 涩综合婷婷| 色婷婷免费观看| 五月丁香六月婷婷久久肏| 岛国AV网| 狼友视频在线观看18| 蜜臀99精品| 五月丁香色六月激情干大屄| 丁香六月激情| www.激情| 婷婷不卡基地| 色婷婷五月综合在线| 色九九七七| 在线观看亚洲AV| 亚洲超级碰| 色情五月婷| 99re视频在线播放| 五月丁香婷婷久久| XX色综合| 九九热视频在线观看| 五月天婷婷激情| 99热免费| 色色五月丁香婷婷综合| 日本人妻A片成人免费看片| 五月丁香综合在线| 激情综合网,婷婷| 天天拍夜夜爽| 久久久久久久久99精品| 午夜天堂一区人妻| 很很色丁香久久停停| 丁香五月大香蕉AV| 激情影院内射| 亭亭五月丁香五月天激情| 来吧亚洲综合网| 91狠狠色色丁香婷婷综合久久| 色综合久| 超碰京东热av男人的天堂| 激情图片久久| 26UUU在线观看| 欧美婷婷五月丁香| 99精品亚洲| CHINESE熟女老女人HD视频| 亚洲字幕AV一区二区三区四区| 国内熟女黄色系列| 久久五月天激情美女| 思思热99er在线视频| 青草激情在线| 丁香激情五月天| 99精品偷自拍| 在线色色| 五月天 无码| 激情婷婷五月天| se色婷婷视频| 九九熱最新視頻| 丁香五月婷婷乱| 人妻久久久久久| 五月婷婷激情五月| 五月天停停日日| 色婷婷丁香六月| 丁香婷婷成人网| a在线观看| 色五月情| 如何安全看伊人婷婷| 久久思思热视频| 99精品在线观看视频| 玖玖婷婷五月天| 色yeye欧美| 久久激情视频| 五月婷婷成人| 婷婷伊人綜合中文| 99色看| 九九热精品99| 爆乳熟女-区二区三区| 中文字幕在线免费观看视频| 狠狠草在线观看| 99久久婷婷| 九伊人网| 五月婷婷 激情五月| 99热精品在线观看| 97碰碰人人| 日本熟女内射| 五月丁香六月片| AV在线资源| 亚洲精品婷婷| 黄色短视频在线观看| 色五月丁香总合网| 色99网站| 久久久91| 久久综合五月天| 亚洲狠9| 色视频2025| 色婷婷五月天久久| 精品综合爱| 六月婷婷私欲| 亚洲精品久久久久久久久久吃药| 亚洲综合新99视频| 天天干天天干天天干| 天天操天天曰天天射| 久久丁香五月婷婷| 日韩精品一区二区三区,四区,五区视频| 日本三级韩三级99久久| 中文字幕av在线| 秋霞av不能| 天天干天天操天天上| 亚洲色热| 99在线观看视频蜜臀| 久热综合| 永久的网站AAAA| 99热老网站| 日本黄色在线观看| 五月综合激情| 996热| 欧美日韩成人高清在线| 综合视频久久| 色婷婷狠狠| 超碰色婷婷| 青草五月天| 国产精品成av人在线视午夜片| 伊人日日干| 婷婷五月天小说| 女性自慰系列第五页| 级情九色| 草操AV在线| 激情五月婷| 任你爽视频| 99久久九九| 狠狠舔| 99性视频| 亚洲射激情| 男男野外做爰全过程69| 99热九九热| 9九色首页| 色综合久久88色综合天天看| 成人av在线电影| 99热亚洲精品| 99成人| av婷婷丁香 六月| 天天爽夜夜操| www.狠狠干com| 1024人妻无码中文字幕| 婷婷成人五月天成人文学| 狠狠色婷婷7777久综合| 特黄三级片| 99久久久久| 九色视频91| 成人婷婷桔色| 久热在线观看视频9| 日韩aaa| 99在线播放视频| 久久99精品视频| 成人五月天在线视频在线观看| 中文字幕无码人妻少妇免费视频| 九九热只有精品| 操人精品| 大香蕉啪啪网| 亚洲色五月婷婷| 婷婷综合亚洲| 综合色色五月| 97色婷婷成人综合在线观看| 欧美综合激情五月| 国产成人在线不卡AV| 美女五月天| 五月天婷婷青青| 日本大逼91| 97视频91| 色久激情在线| 综合亚洲六月婷婷在线| 丁香五月 激情文学| av在线观看免费| 日本女va| 欧美WW在线网| 精品欧美一区二区三区久久久| 丁香五月区| 狠狠丁香| 五月丁香六月婷婷综合| 亚洲乱码日产精品BD| 五月婷婷在线综合| 天天AV导航网| 亚洲综合视频网| 强辱丰满人妻HD中文字幕| 色J香五月天| 五月丁香精品| 丁香婷婷六月| 国产做A爰片毛片A片美国| 黄色激情五月天| 五月天日日操夜夜操| 五月婷婷丁香日韩在线| 五月丁香六月激情| 伊人久久大香蕉网| 五月天 另类图片| 色五月天丁香婷婷| 五月黄色婷婷| 久久久久久久11111111111| 玖玖在线| 色五月婷婷在线观看| 五月色婷婷综合色| 日韩啪| 狠狠婷婷综合| 少妇被躁爽到高潮无码文| 丁香五月天堂网| 青娱乐美女福利视频美臀| 91热视频色网站| 青青久久五月| 久久AAAA片一区二区| 99久在线观看| 99免费在线视频| 激情五月五月五月婷婷| 天天草天天舔| 99久久这里只有精品免费官网| 色综合久久88| 婷婷丁香五月天熟女丝袜| 五月天婷婷影院| 黄色五月婷婷| 婷婷色五月激情强奸四射| 五月丁香人人婷婷在线观看| site:esunnet.com| 色激情综合狠狠婷婷| av在线免费网站 | se色99| 性欧美日本| 九色porny在线观看激情四射| 色五月激情五月| 成人丁香五月| 黄色AV日韩| 日本成人噜噜噜| 狠狠干 狠狠操| 日韩免费乱轮网站| 久久五月天精品视频| 日韩色久| 男女99免费视频| 久久99网址| 97操男人的天堂| 99福利视频导航| 精品国产一区二区三区四区阿崩 | www.maotanji.com| 色私五月婷婷| 精品激情| 99热日韩这里只有精品| 激情婷婷五月天伊人在线观看| 亚洲五月天,激情视频| 天天摸天天肏| 激情 五月 婷婷 丁香| 91人人爽狠狠狠| 色婷婷色九月| 九九色影视| 色综合综合色| 青青草性爱视频| 国产日产成人亚洲欧美国产VA| 五月丁香婷中文| 综合色99| 久久五月丁香六月婷| 26uuu淫色| 五月情四婷婷| 国语精品探花| 五月婷婷啪啪| 婷婷五月色情天| 六月婷婷激情| 成人视频网| 风流少妇A片一区二区蜜桃| 最近中文字幕大全免费版在线| 国产亚洲精品AAAAAAA片| 风流少妇A片一区二区蜜桃| 99色色| 男女啪啪做爰高潮无遮挡 | 丁香青青五月天| 一级性感毛片| 欧美日韩99| www久久五月com| 亚洲综合干| 操你av| 婷婷激情视频欧美视频自拍视频欧美剧 | 九九色综合网| 我爱大香蕉| 狠狠CAO日日穞夜夜穞AV | 天天拍夜夜爽| 国产97色在线 | 日韩| 亚洲av网站| 热久久这里只有精品| 北京熟妇搡BBBB搡BBBB| 人人草碰| 在线观看熟女少妇| 五月婷婷六月丁香在线视频| 在线播放中文字幕| 国产av网| 5月激情天| 狠色狠色狠色狠色狠色网| 99热亚洲精品| 99热超碰在线| 亚州婷婷五月激情综合| 六月丁香成人| 丁香激情五月天| 思思热视频在线观看| 久久小说网| 欧美激情 日韩无码 婷婷 五月天| 婷婷五月色综合| 国产五月丁香在线| 激情久久丁香| 五月激情丁香啪啪| 欧美A级网站| 久久九九大香蕉电院| 99热免费精品| 色欲五月丁香| 欧美va亚洲va| 婷婷五月天av| 成人精品免费在线观看| 人人澡天天色天天做| 色丁香影院| 五月天婷婷无码| 超碰成人影视| 天天操夜夜夜拍拍拍| 欧美色色色色色色色色色色| 操逼五月婷婷| 丁香六月色婷婷欧美| 国产五月天欧美色| 日本人妻伦在线中文字幕 | 婷婷激情丁香五月天综合| http://www.sd-xiangsu.com/| 99精品在线| 99爱在线| 伊人五月久久| 99色在线视频| 五月婷网| 99热精品在线观看| 91人无码久久久久久| 亚洲va日| 97在线精品| 人妻激情网| 色五月天综合| 五月丁香久久| 久久只有精| 97色色色| 婷婷99狠| 99色视频免费在线规看| 国产精品VIDEOSSEX久久发布| 91婷婷伊人牛牛| 996热re视频精品视频这里| 亚洲成人免费在线| 五月丁香在线视频观看| 五月婷av| WWW久久久| 精品无吗va视频免费观看| 日韩黄在免| 五月色婷婷亚洲| 色一情一乱一乱一区91| 啪啪婷婷五月天激情| www.深爱激情| Av免费网站在线| 777精品成人a v久久| 婷婷五月在线视频| 5月婷婷综合| 日韩啪啪网| 国产精品视频| 另类A片| 日韩无码乱轮| 在线视频激情网站| 91精品又长又大又粗又爽又猛| 99爱在线观看视频| ady狠狠入| 婷婷五月天亚洲综合| 伊人在线视频| 五月丁香久久呀| 96精品成人无码A片观看金桔| 26uuu.| 亚洲激情四射| 婷婷五月婷婷五月天| 色伦专区97中文字幕| 色亚洲中文| 99热这里| 天天干天天玩天天夜天天射天天操天天日蜜臀少妇 | www.99热| 夜夜操夜夜姧| 婷婷综合久久综合| 99综合| 光棍影院日韩精品| 97碰超级人人看| 色综合色五月| AA丁香综合激情| 日韩五月婷婷| 国产看真人毛片爱做A片| 五月天五月色| 91九色成人原创视频| 这里只有精品免费| 97在线视频人妻九色| 色婷婷导航| 一区色色色色网| 成功精品影院| 。久久久久久久久久久久久久人妻| 99色人| 天天干天天操天天爽| 激情视频综合| 99色精品| 台湾佬天天日丁香婷婷五月天| 婷婷六月偷拍| 中美日韩成人在线| 99热精品在线播放观看| 991自拍视频| 大香蕉欧美在线| 超碰av在线| 五月丁香六月婷| 五月WWW| 五月色亚洲| 久色网| 丁香五月大片| 色五月婷婷AV| 五月色综合| 五月丁香婷在线| 91啪啪啪啪| 色爱亚洲| www,26uuu,c0m,色情| 九九色99| 色操综合| 色色性爱视频| 丁香六月婷婷综合欧美| 五月丁香狠狠爱| 久久婷婷五月天大香蕉| 五月丁香婷婷综合久久| 五月丁香亭亭天天舔| 国产免费av在线| 噜噜噜久久| 久久婷婷五月综合色和| 双性美人被调教到喷水A片| 五月婷在线色视频| 人妻激情综合| 欧美97超碰| 另类A片| 狠狠狠狠狠狠狠狠草| 九九精品99久久久| 日本一级淫| 狼友视频在线观看18| 5月婷婷六月丁香| 久久久性爱网| 亚洲精品第一国产综合亚AV| 激情网五月| 六月丁香久久| 欧美成人网婷婷综合在线| 欧美日韩成人高清在线| 色五月天婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷 | 婷婷色色五月天| 亚洲五月停停| 9999热这里只有精品| 性无码专区无码| 色情五月综合婷婷| 五月婷六月天| 久久五月天综合视频网站| 狠狠爱婷婷色| 九九无毛| 激情性爱五月天网页| 婷婷在线视频| 久99久热| 狠狠干天天日| 五月天激情无码| WWW.桔色成人.COM入口| 狠狠色丁香综合| 玖玖午夜视频| 日本色色影院| 国产探花一片区| 免费视频WWW在线观看网站| 亚洲综合99| 色综合久久88色综合天天99| A久网| 婷婷五月天直播| 五月丁香婷婷综合| 久久久久亚洲AV成人无码电影| 成人无码中文| YW无码| 综合色色五月| 婷婷香蕉精品| 97一区二区| 国产JK精品白丝AV在线观看| 九九激情网| 色九九综合| 婷婷综合视频| 欧美三级欧美一级| VA色婷婷| 久久99视频| AV五月丁香| 91丨九色丨熟女丰满| 五月天开心婷婷激情网站| 国色天香伊人狠狠色| 深爱婷婷色| 婷婷日| 色久在| 天天五月香欧美| 丁香五月婷婷亚洲人| 在线中文字幕视频| 丁香五月婷婷狠狠色| 色情综合| 天天综合亚洲综合网天天αⅴ| 91人妻色色网| 久久在这里有精品| 99.色| 99热这里只有国产精品| 99综合激情久久精品久久| 99热精品6| 婷婷五月天干干| 激情综合色五月丁香六月亚洲| 99热这里只有精品1998| 五月丁香六月婷婷亚洲视频| 六月婷婷在线视频| 麻豆雪千夏| 久久新地址| 高清无码视频网址| 99热这里| 久久丁香婷| 色欧美日| 国产精品久久久久久白浆色欲| 99啪啪| 九九爱这里只有精品| 天天粽合合合合| 丁香五月在线视频黑人| 天天干天天干天天干天天干天天干| 天天综合网站| 亚洲久久激情| 99久久户外勾搭| 日本三级日本黄色| 激情九色| 涩涩五月天综合| 俺去也在线官网| 婷婷五月天小说网| 婷婷色婷婷| 狠狠综合网| 67久久| 激情五月丁香六月综合AVXXXX| 色欲天天综合| 久色中文| 五月天天天天天天天天天天天婷婷婷| 99久久久99久久91熟女| 黄色视频网站在线播放| 国产成人AV在线播放| 那里有AV网址| 天天做天天摸| 亚洲色婷婷五月天| 中文字幕av久久爽| 大香蕉伊人久久| 九九九九九九九热| 丁香激情网| 99国产精品久久久久久久久久久| 日韩有码久久| 五月丁香综合网色欲| 深爱1激情网| 深夜男女福利刺激影院一区完整| 超碰免费人| 成人av在线网址| 天天狠狠插| 婷婷五月激情网| 丁香五月天社区| 色色丁香五月| 99视频精品全部免费 在线| 丁香五月影院| 七七婷婷综合| 五月婷在线观看| 婷婷爱五月天人人爱| 97操视频| 91趴趴| 九九视频这里是精品五月| 舔色婷婷| 久久婷婷老| 婷婷五月天国产精品| 五月婷婷基地| 精品无码久久久久久久久| 91精产品自偷自偷综合| 久久人妻高清中文| 色色婷婷五月天| 婷婷五月丁香香蕉| 五月丁香婷在线| 婷婷爱五月天| 久久婷狠狠色| 26UUU精品一区二区| 青草青草视频2免费观看| 色碰碰| 日韩无码色色| 久热99视频在线观看| 《诡秘之主》在线观看| 97精品自拍| 99日视频在线| 五月婷婷之美女图片| 777精品久无码人妻蜜桃| 97色色色| 五月天亚洲综合网| 五月天啪啪网| 99热精国产这里只有精品| www.夜夜操.com| 色五月五月婷婷| 五月的色婷婷高潮| 思思热99er| 欧美婷| 天天干一干| 99热这里只有精品26| 97人人操人人| 97影院一级片| 99丁香五月婷| 任我鲁这里有精品视频| 色播播婷婷| 婷婷性爱五月天丁香网| 五月天精品综合在线| 全部老头和老太XXXXX| 精品99这里有| 五月香婷婷| 丁香五月天在线观看视频| 欧洲综合视频| 日本超碰在线| 五月激情婷婷在线| 五月婷婷免费在线| 婷婷五月成人| 丁香五月天天| 成人精品视频99在线观看免费| 久久视屏这里只有久久| 五月丁香啪啪| 先锋男人99资源| www.色五月| 草婷婷在线| 综合色图婷婷| 99色免费观看全部| 超级碰碰碰碰视频| 97干欧美| 99在线观看视频免费| www婷婷| 99国产小视频免费观看| 日本九九网| 婷婷久久五月| 成人色色视频| site:pnnrt.com| 色狠狠色噜噜噜a天堂一区| 婷婷射图五月天| 五月婷婷五月丁香综合| 久久五月丁香综合17C| 亚洲五月花| 色色婷婷色色| 99色色网| 欧美精品久久久久久视频观看| 年轻的妺妺伦理HD中文| 五月婷婷激情综合视频| 99免费青青蜜臀| 91视频精品99| 婷婷五月天天天日日夜夜| 五月天激情网站| 亚洲人妻一区二区| 亚洲人妻电影| 五月天激情综合| 婷婷五月丁香激情色情| 国内在线99视频| 久久免费操| 五月天婷五月天综合网小说首页-五月天激激婷婷大综合,婷婷亚洲综合五月天小说 | 国产在线6| 不卡在线视频| 99这里有精品视频| Av性爱网| 999九九九久久久99HD| 婷婷五月天激情电影| 伊人丁香六月婷婷| www91色网站| 日韩在线9| 婷婷国产日本欧美| 亚洲欧美国产A片免费观看| 色呦呦美女| 色色色视频免费无码 | 色婷婷六月丁香综合欲精品| 婷色五月天| 被男人添B超爽视频| 天天日综合| 婷婷激情中文综合| 丁香五月天婷婷大香蕉| 五月丁香色综合| 婷婷丁香综合| 六月婷婷色综合| 日本综合九九| 人妻精品一区二区三区| 日韩在线婷婷五月天综合| 九九99精品视频在线观看| 婷婷五月天性色| 色六月婷婷| 亚洲精品性色| 天天操天天爱天天日| 四季日韩AV无码综合| 婷婷五月婷婷| 天天日综合| 久久视频婷婷视频| 国产精品成人AV在线| 精品少妇人妻AV无码专区偷人| 欧美影院| 99热只有这里才是精品| 久久无码激情视频| 大香蕉五月| 五月天社区婷婷| 日韩AV大全| 五月天婷婷成人| 狠狠狠狠狠狠草| 97人人操人人| 久热精品在看| 五月停性愛| 丁香激情网| 99riAV国产精品视频| 婷婷五月天第四色| 99热欧| 九色91美女| 九九精品碰| AV大片在线播放| 色色色热| 成人AV在线电影| 人妻少妇色综合| 色婷婷五月天小说| www 五月天 com| 亚洲性天天| 成人版视频在线观看| 九月丁香婷婷网| 成人无码精品1区2区3区免费看 | 色色无码| 99久久6| 五月色精品| 亚洲综合视频一下| 久久激情综合| 天天综合久久| 青青.com| 色色五月婷| 激情久久久久久| 激情av在线| 五月婷婷草| 婷婷丁香综合在线| 久久天堂女人| ztEJj| 伊人大综合| 五月婷婷六月激情| 丁香情色五月| 日韩久久系列| 蜜臀综合久草| 五月九九综合| 色婷婷啪啪综合网| 无码一区二区三区四区五区91c| 九九色网专区| 级人人91| 97人人操人| 人人操人人看97干| www.com.色色| 综合色网站| 久久色五月天| 大香蕉天堂| 综合久久综合久久| 91九色在线| 99热99成人| 青青草a在线| 婷婷五六日| 日在线V视频在线播放| 成人网站免费sxj| 丁香婷五月| 婷婷色欧美激情| 成人五月天视频| 天天日 天天草| 中文在线成人| 婷婷伊人綜合中文字幕| 九九黄色网| 国产精品成人AV在线观看春天| 九九综合影音先锋| 五月婷婷9| 色人久夂| 色五月天.con| 青青草深爱激情网| 91精品综合久久久久久五月丁香 | 久热无码| 久久五月网| 色婷婷裸体色性在线| 丁香婷婷五月天在线视频| 丁香五月区| 99久久99九九99九九九| 久草婷婷网| www.久9| 99日本黄站| site:picc-up.com| 五月婷视屏在线观看| 91青娱乐青青草| 91色婷婷综合久久中文字幕二区| 99视频在线观看地址| 91欧美日韩| 99九九在线观看免费| 日日操夜夜爽白洁| 色色免费网战视频| 天天色丁香| 丁香五月色情| 色yeye色综合| 久/久精品99看9| 99色热视频| 激情五月天婷婷| 狠狠爱综合网| 综合久久8| 99久久婷婷国产综合精品草原| 无码激情精品色婷婷久久久久| 天天婷婷综合亚洲亚洲| 婷婷五月天视频| 丁香五月婷婷老师网站| 婷婷伊人网| 丁香五月激情性色郤| 丁香五月手机在线| 国产精品久久久久9999小说| 婷婷丁香成人五月天| 婷婷色五月激情| 欧美婷婷成人| 99热精品在线| 国产视频福利| 色婷五月天网站| 99久在线视频| 五月婷婷色色爱| 亚洲永久免费| 天天插AV丝袜中| 九九激情| 丁香久月| 五月婷婷狠狠干| 欧美精品999| 色情激情五月婷婷| 亚洲激情淫网| 五月婷婷深深爱| 五月丁香亭亭电影久久| 超碰99在线观看| 激情综合网五月激情| 色色操| 91丨九色丨白浆秘| 天天摸色吧天天摸色吧| 色婷婷激情| 99在线免费视频| 激情五月婷婷老师| 婷婷五月天激情四射| 99啪啪网| 婷婷丁香五月亚洲综合网在线视频观看| 99超级碰免费视频| 久久9RE热视频精品98| 五月天色婷婷图片| 99精品在这里| 免费黄色AV| 久久人妻视步| 国产成人精品亚洲线观看| 天天搡日日搡aaaaⅩ| 五月叮香啪| 九九色情网站| 五月天婷婷一起草| 五月婷婷基地| 97人人操| 天天舔天天爽| ww超碰在线| 久热这里只有精品视频6| 激情深爱五月天| 黄网免费观看| 五月婷婷丁香| 狠狠九九婷婷韩| 色婷婷五月天小说| 久久艹 五月天| 婷婷成人综合免费视频| 九九在线精品| 六月丁香啪啪| 色五月首页| 久9热在线视频| 婷婷中文字幕网| 久久久久久18| 五月丁香在线看| 久久五月天影院| 亚洲精品性色| 五月天综合在线网| 美女要搞搞天天搞搞搞网站| 五月丁香大香蕉| 久久五月天激情婷婷| www色五月| 俺也去在线久久精品23欧美综合视频网站,丰满人妻一区二区三区在线视频53,丰满 | 超碰网站在线观看| 91大屁股精品| 999久久久国产精品| 欧美日韩国产一区二区| 色婷婷五月天偷拍| 九九超碰人人| www.色五月| 9月色婷婷| 五月丁香无码| 久99热| 天天日夜夜拍| 中文字幕丰满乱孑伦无码专区| 91一起操| 婷婷九月激情| 变态 另类 在线| 思思精品久久艹| 丁香五月婷婷香| 亚洲精品午夜国产va久久成人| 欧亚中文A V| 天天做天天爱天天玩| 五月丁香久久呀| 91色久| WWW夜夜| 成人做爰黄A片免费看直播室男男| http://www.lingjunshare.com/ | www.久久五月天.com| 五月天大香蕉av| 激情五月,婷婷五月,丁香五月| 久久九九婷婷| 五月丁香六月婷综合成人综合 | 五月色激情综合网| 丁香五月婷婷五月| 日本超碰在线| 亚洲精品又粗又大又爽A片 | 丁香婷婷九月| 色吧五月| 伊人无码高清| 第四色首页| 激情文学第四色婷婷丁香五月| 丁香五月色| 六月香五月婷| 丁香香蕉婷婷| 激情丁香婷婷| 天天干天天日日| 97操女视频| 婷婷五月天综合网| 狠狠另类视频| 婷婷激情五月天激情小说| www.99热在线观看| 中文字幕+乱码+中文字幕在线观看| 激情综合网激情五月婷婷| 日本成人噜噜噜| 亚洲久热| 影音先锋男人站,影音先锋男人色资源网,影音先锋AV最新资源站,影音先锋AV资源 | 色婷婷在线影院| 色婷婷影院| 人妻操在线看| 99毛片| 精国产品一区二区三区A片| 六月久久狠狠| 伊人久久婷婷| 婷婷碰碰| 九九综合| 五月婷婷花| 婷婷午夜激情| 大香伊人久色| 久久五月丁香婷婷| 婷婷丁香五月欧美人| 99riAV国产精品视频| 国产毛多水多女人A片| 人妻久久久久久久| 二人电影免费版在线观看| 91综合在线观看| 99性爱| 99视频精品在线| 综合婷婷六月| 婷婷综合在线播放| 熟妇人妻中文字幕无码老熟妇| 天天爽天天爽| 五月天婷婷伊人| 久碰久操| 亚洲成人综合网在线免费观看| 色婷婷狠狠| 综合噜噜| 色婷婷丁香特级性爱视频| 黄色成人网站在线播放| 国产操B| 欧美日韩成人| 亚洲最大视频| 丁香亚洲婷婷五月| 91偷拍视频| 婷婷丁香综合色AV| 丰满少妇猛烈A片免费看观看| 成人短视频在线免费观看| 求可以看的AV网址| 激情综合五月丁香| 婷婷色六月| 色五月激情五月| 99热超碰在线| 五月丁香激情综合网| 先锋男人99资源| 综合久久婷婷| 成人在线网站| 婷婷色综合中心站| 国产肥白大熟妇BBBB视频 | 久久这里只有欧美| 婷婷丁香午夜综合影视| 九九九热精品| 狠狠综合区| 国产九月婷婷| 9久热精品在线视频| 五月丁香黄色视频| 狠狠色噜噜狠狠| 色五开心五月五月深深爱| 日韩黄黄| 亚洲精品色色| 丁香色色网| 久久艹99| 婷婷中文字幕网| 极品少妇婷婷五月| 超91热| 江苏少妇性BBB搡BBB爽爽爽| 久久久久婷婷| 欧美色婷婷| 超碰在线免费| 五月天伊人久久久久| 色婷婷www| 99re在线这里只有精品视频首页| 天天草天天舔| 思思热思在线精品视频| 五月丁香猫咪久久婷婷综合视频激情四射网入口 | 六月婷婷国产| Va另类视频| 激情合网婷婷| 狠狠色狠狠鲁| 五月婷婷色丁香| 天天在线久久综合| 激情五月天综合图片小说网站| 天天插天天狠| 永久的网站AAAA| 久久永久网址| 亚洲另类婷婷五月丁香在线播放| 99色婷婷视频| 婷婷五月天AV网| 秋霞免费三级片| 色综合网上班开心婷婷久久| www超碰| 六月色婷婷色| 激情五月图| 六月色色综合| 天天插夜夜爽| 色色色色色爱| 六月丁香久久| 99热这里只有精品9| 亚洲午夜一区二区| 婷婷99中文字幕| 99自拍视频| 日本久久精品| 办公室少妇激情呻吟A片在线观看| 国外亚洲成AV人片在线观看| 国产在线aaa片一区二区99| 国产露脸150部国语对白| 1024亚洲无码| 久草婷| 色涩影院六月丁香| 91视频一起草| 99色综合网| 丁香婷婷少妇| 五月婷婷伊人在线| 激情综合网五月天| 最新色色五月天| 色色色色热| 强辱丰满人妻HD中文字幕| 亚洲六月色| 婷婷色五月天色色| 原琪琪色影院| 美妞av| 亚洲久热无码| 色色色综合| 五月婷六月| 午夜精品久久久久久久爽| av婷婷丁香| 99热在线资源| 蜜乳9188| 99久久久国产精品免费蜜乳tv| 噜噜色婷婷| caop在线| 国产特级毛片AAAAAAA高清| 婷婷丁香精品视频在线观看| 色欧美影院| 婷婷丁香五月激情综合站_久久五月丁香激情综合_开心五月综合激情综合五月_婷 | 超碰二区| 成人无码髙潮喷水A片| 久久婷鲁| 精品成人久久久久久久_一二三四视| 91艹人| 99无码黄色视频| 婷婷精品| 99精品综合| 久久东京热婷婷五月| 综合色天天| 五月天播播| 激情五月天丁香| 艹色18p| 亚洲va欧美| 亚洲欧美另类在线23p| 99热都是精品| 色五月丁香91| 五月丁香啪综合| 色综合久久天天综合网| 亚洲免费av在线| 无码日本精品XXXXXXXXX | 久久婷婷资源| 久久小视频免费| 天天干天天爽| 色www久视频| 女操碰| 天天操,天天插| 99精品久久久| 日韩五月婷婷久久| 色婷婷影院| 五月丁香六月婷婷国产视频| 色五月五月婷婷| 综合九九久久| 五月婷婷视频啪啪美女| 五月婷婷草| 五月色情| 丁香九月激情| 天天久| 黑人巨粗进入警花疼哭A片| 九九自拍网| 99热这里只有精品最新| 亚洲五月天激情| 十区AV| 人妻肉射免费观看| AV人人操| 五月丁香色婷基地综合久久| 五月丁香六月激情狠狠| 五月丁香香蕉| 伊人9草在线观看| 亚洲五月天伊人| 丁香五月播播| 亚洲XX网| 久久99免费视频| 国产亚洲精品AAAA片APP| 久99视频在线观看| 色播激情五月天| 大色鬼综合| 五月色婷婷在线观看| 五月婷婷草| 9l久久久视频| 五月天婷婷色小说| 国产精品美女| 碰碰女| 婷婷五月天狠狠色| 亚洲成人av中文| se99视频| 另类小说色婷婷| 亚洲偷| 久久这里只有国产| 97超碰在线免费观看| 久久这里只有精品视频15 | 久久婷婷五| 婷婷五月天a| 中文字幕日产A片在线看| 热九九精品| 久久婷婷国产| 亚洲XX网| 综合久久99| 91碰碰碰久久久久| 亚洲色vA| 国产一级视频a| 色婷婷视频| 婷婷五月天综合网| 九九色影院| 丁香五月综合婷婷| 97五月婷婷| 亚洲精品永久久久久久| 亚洲最大视频网站| 天天色激情| 婷婷伊人五月天| 亚洲六月婷| 少妇高潮呻吟A片免费看软件| 思思久久精品视频| 丁香六月啪| 综合久久婷婷五月丁香| www.天天日| 五月丁香六月婷婷亚洲天堂网站| 操碰91| 色婷婷五月天中文字幕| 亚洲免费婷婷| 99热99网| 天天天天操| 久热这里有精品视频| 麻豆AV一区二区三区| 激情婷婷亚洲五月| 青青久在线视频免费观看| 色五月婷婷在线视频| 99热久久这里只有精品| 99热99免费| 丁香88AV五月婷婷| 五月丁香六月香综合激情| ZpRSw| 夜夜操夜夜操| 97色女人在线| 国产亚洲色婷婷久久99精品91| jiujiu热在线视频| 亚洲操人| www.色窝| a级毛片一区二区免费视频| 婷婷五月花丁香| caopeng97人人| AV在线大香蕉| 天天色月| 日韩少妇内射免费播放| 操你av| 国产亚洲色婷婷久久99精品9j| 无码橾| 天天做天天要天天爱| 99热在线观看| 五月婷婷视频28| 日韩一级网站| 婷婷五月激情综合| 一區四區歐美日韓| 中文AⅤ大全| 婷婷五月天丁香社区| 丁香五月天导航| 国产五月视频| 狠狠人人婷婷| 激情五月天视频| 大地资源色婷婷视频在线| 在线可以看的av网址| 欧洲S级在线观看| 99热这里只有精品55| 激情五月婷婷综合视频| 碰超在线九色| 99九九久久| www.色窝| 丁香六月综合激| 97人人射| 激情婷婷五月天在线观看| 美欧成人视频| www.激情| 色婷婷www| 欧亚洲在线高清视频| 中文成人在线| 天天干一干| 九九成人高清视频| 五月婷婷丁香综合,亚洲天堂| 日本精品99| 伊人婷婷五月| 精品99在线| 少妇搡BBBB搡BBB搡毛茸茸| 五月天综合在线观看视频| 久久婷婷五月综合97色一本| 久久婷综| 亚洲综合色婷婷| 色婷婷激情视频| 午夜爱插插| 曰韩五月丁香色婷婷无码| 久久久香| av在线色五月丁香婷区久| 99九九热在线观看| 丁香五月婷婷社区| 五月天精品视频|