亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(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等類型為主涵蓋服務(wù)器端代碼、Unity客戶端工程、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目錄用于客戶端界面開(kāi)發(fā)Proto目錄幫助理解協(xié)議定義。通過(guò)該Demo新手可以快速了解ET框架的整體結(jié)構(gòu)掌握服務(wù)器與客戶端代碼的組織方式理解網(wǎng)絡(luò)通信與熱更新流程并熟悉Unity中游戲界面的設(shè)計(jì)思路。代碼結(jié)構(gòu)清晰對(duì)于希望從零搭建ET框架項(xiàng)目的開(kāi)發(fā)者這份Demo提供了可直接運(yùn)行的參考是理論與實(shí)踐結(jié)合的入門佳選。1. 基于ET框架的斗地主Demo先跑通一桌牌再談框架選型斗地主這種牌局在牌類項(xiàng)目里屬于“看著簡(jiǎn)單、寫起來(lái)全是細(xì)節(jié)”的活兒54張牌的組合判斷、叫地主的三分制、順子炸彈的壓牌規(guī)則任何一條沒(méi)定義清楚對(duì)局就會(huì)在第三輪出牌時(shí)突然翻車?;贓T框架的斗地主Demo就是把ET框架這套以實(shí)體組件為核心、自帶消息分發(fā)和服務(wù)端熱更的C#游戲框架用來(lái)做一桌能完整跑起來(lái)的斗地主牌局。它的價(jià)值在于驗(yàn)證房間類游戲最關(guān)鍵的三件事消息觸發(fā)房間狀態(tài)流轉(zhuǎn)是否順滑、服務(wù)端熱更能不能支撐牌局邏輯快速迭代、多人同時(shí)出牌時(shí)狀態(tài)是否一致。這篇筆記適合第一次碰ET框架、又想以牌局練手的開(kāi)發(fā)者也適合客戶端程序員想順著Demo理解服務(wù)端消息鏈路、真實(shí)跑通一次。下面按框架原理、本地環(huán)境、核心邏輯、避坑、驗(yàn)證來(lái)展開(kāi)。2. ET框架的分層架構(gòu)與消息流轉(zhuǎn)斗地主Demo為什么適合這樣搭在寫任何代碼之前先把ET框架里“實(shí)體、組件、事件、消息”四個(gè)概念和斗地主的對(duì)應(yīng)關(guān)系理清楚。很多人在ET上做第一個(gè)項(xiàng)目時(shí)容易把服務(wù)端寫成一堆靜態(tài)類加單例那等于繞開(kāi)了框架的核心價(jià)值后面做房間管理和熱更都會(huì)很別扭。2.1 實(shí)體-組件與事件系統(tǒng)框架的“骨”和“筋”ET框架里最基礎(chǔ)的單位是Entity它不是一個(gè)具體的業(yè)務(wù)對(duì)象而是一個(gè)空殼。數(shù)據(jù)住在Component里邏輯寫在System或者Handler里。對(duì)應(yīng)到斗地主Demo一張桌子、一個(gè)玩家、一場(chǎng)對(duì)局都是Entity桌面上的公共狀態(tài)和某個(gè)玩家的私有手牌則分別是不同的Component。常見(jiàn)做法是這樣定義兩塊數(shù)據(jù)// Model層只放數(shù)據(jù)定義不寫玩法邏輯 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è)類直接繼承Entity也沒(méi)有問(wèn)題按你用的分支來(lái)。事件系統(tǒng)則是用來(lái)解耦的。比如玩家進(jìn)入桌子后要觸發(fā)“通知其他玩家”、“推送手牌”、“記錄日志”三件事如果用同步調(diào)用寫在一起后面每加一個(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ì)斗地主這種回合明確、事件種類少的項(xiàng)目事件系統(tǒng)能讓你把“出牌”和“出牌之后的推送”拆開(kāi)調(diào)試時(shí)只盯一個(gè)環(huán)節(jié)。2.2 一條出牌消息的完整旅程從客戶端按鈕到服務(wù)端廣播斗地主Demo里最典型的鏈路是出牌??蛻舳巳齻€(gè)玩家其中一個(gè)點(diǎn)擊“出牌”選了幾張牌點(diǎn)確定之后發(fā)生的事情可以拆成六個(gè)步驟。客戶端構(gòu)造消息并發(fā)送// 客戶端把選中的牌封裝成消息 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)失敗客戶端要立刻回滾手牌狀態(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作為連接載體可以在上面掛用戶信息組件二是業(yè)務(wù)邏輯不寫在Handler里而是放在CardLogic這種靜態(tà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 自寫路由自己實(shí)現(xiàn)線程模型無(wú)自己寫教學(xué)、初級(jí)DemoMirror / UNET主從同步為主弱組件同步合作類、小規(guī)模聯(lián)機(jī)ET框架多進(jìn)程分布式支持Hotfix熱更Handler Opcode房間類、MMO、牌局原生Socket做斗地主要處理的粘包拆包、心跳、重連、消息序號(hào)每一項(xiàng)都需要自己寫寫三個(gè)月后你得到的只是一個(gè)能跑通的通信庫(kù)牌局邏輯還沒(méi)開(kāi)始。用Mirror這類同步庫(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)工程客戶端是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é)客戶端連接和轉(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管客戶端連接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ù)端與客戶端鏈路就通了。3.2 創(chuàng)建房間與加入用一條Call消息打通客戶端到服務(wù)端鏈路通了之后第一個(gè)功能是創(chuàng)建房間??蛻舳它c(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)給客戶端 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ù)上。這樣房間銷毀時(shí)所有子組件一起釋放不會(huì)留下孤兒實(shí)體。客戶端收到房間號(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; // 房間滿了 }3.3 自測(cè)與日志如何判斷鏈路真的通了跑Demo最怕的是“看起來(lái)啥都沒(méi)發(fā)生”。我一般通過(guò)三條日志確認(rèn)鏈路第一服務(wù)端Gate進(jìn)程出現(xiàn)“客戶端連接成功”的日志說(shuō)明TCP連接建立了。第二客戶端發(fā)起登錄后Realm進(jìn)程出現(xiàn)“驗(yàn)證成功”日志說(shuō)明消息路由到了Realm。第三創(chuàng)建房間后Map進(jìn)程出現(xiàn)“房間創(chuàng)建成功”日志同時(shí)客戶端界面跳轉(zhuǎn)到了牌桌場(chǎng)景。如果卡在某一步最常見(jiàn)的檢查點(diǎn)消息Opcode是否正確注冊(cè)、客戶端連接的端口是不是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é)算 }叫地主的流程可以寫成一個(gè)純函數(shù)服務(wù)端Handler只負(fù)責(zé)把客戶端傳來(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最核心的部分也是新手最容易翻車的地方。先把牌型枚舉列出來(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ò)非炸彈同類型牌比主牌大小其他情況不能壓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ù)寫完后要單獨(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在這里偷懶直接把房間銷毀、讓玩家重新建房但這會(huì)給客戶端帶來(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; } }重置不等于銷毀這是兩個(gè)概念。銷毀房間會(huì)導(dǎo)致所有玩家斷線重置則讓同一批玩家無(wú)縫開(kāi)始下一局體驗(yàn)完全不同。5. 避坑ET框架寫斗地主的5個(gè)典型踩坑記錄這一章記錄的都是在ET框架上做牌局項(xiàng)目最常見(jiàn)的坑。每一條都是“現(xiàn)象、原因、解決”三段式基本覆蓋了從熱更、消息路由到并發(fā)和資源清理的問(wèn)題。5.1 改了Hotfix邏輯卻不生效現(xiàn)象改完出牌判斷邏輯Unity客戶端重新運(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ì)寫一個(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)象客戶端發(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)按模塊分段比如房間類消息從10001開(kāi)始牌局類消息從20001開(kāi)始登錄類從30001開(kāi)始。新加消息時(shí)先查一遍現(xiàn)有Opcode而不是順眼就復(fù)制。框架本身有一些工具能檢查重復(fù)但我還是建議自己維護(hù)一個(gè)消息清單新消息在清單里登記編號(hào)。5.3 客戶端和服務(wù)端手牌狀態(tài)不一致現(xiàn)象客戶端顯示玩家A手上還有5張牌服務(wù)端記錄只有4張。再出幾次兩邊手牌數(shù)量差得越來(lái)越多最終某次出牌被服務(wù)端拒絕玩家卡死。原因客戶端在發(fā)送出牌請(qǐng)求后立即做了本地手牌移除而沒(méi)有等服務(wù)端確認(rèn)。服務(wù)端校驗(yàn)失敗時(shí)客戶端沒(méi)有收到失敗回執(zhí)或者收到了但沒(méi)有執(zhí)行回滾。解決客戶端必須先出牌請(qǐng)求等服務(wù)端返回成功后才更新本地手牌。我在Demo里統(tǒng)一用Call而不是Send服務(wù)端返回成功或失敗客戶端只信響應(yīng)。這會(huì)有一次RTT的延遲但牌局游戲?qū)O低延遲不敏感一致性優(yōu)先級(jí)更高。5.4 多線程下共用List導(dǎo)致牌序錯(cuò)亂現(xiàn)象服務(wù)端偶爾出現(xiàn)手牌列表里多了一張、少了一張或者出牌順序偶發(fā)混亂。不頻繁但一出現(xiàn)就導(dǎo)致整局無(wú)法繼續(xù)。原因ET框架底層會(huì)起多個(gè)線程處理網(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)一回主邏輯線程操作。ET框架提供了同步上下文機(jī)制在Handler里用異步調(diào)度把真正修改房間數(shù)據(jù)的代碼切回主線程避免多個(gè)線程交叉訪問(wèn)。具體做法是把實(shí)際邏輯放到Room實(shí)體的System里由房間Actor串行處理消息只是一個(gè)觸發(fā)信號(hào)。Actor模型天然串行處理同一實(shí)體的消息這是ET框架處理房間類玩法的標(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)始后還在推送。原因房間銷毀或重置時(shí)沒(méi)有移除這個(gè)房間實(shí)體上的消息訂閱也沒(méi)有清理Actor消息隊(duì)列。上一局延遲的消息在新一局開(kāi)始后繼續(xù)投遞到同一個(gè)RoomEntity導(dǎo)致?tīng)顟B(tài)污染。解決房間銷毀前必須做清理調(diào)用RemoveComponent移除牌局組件取消訂閱的事件清空MessageQueue。如果是重置而不是銷毀要保證消息隊(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能跑通只是第一步證明它總是正確是另一回事。牌局類項(xiàng)目最適合用“對(duì)拍”來(lái)驗(yàn)證寫一批構(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)); }這類用例要覆蓋單張、對(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ù)雜工具寫一個(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ù)盤最近一次做類似項(xiàng)目我把牌型對(duì)拍腳本、30路壓測(cè)和局號(hào)日志三樣都上了。效果是排查消息串線從“靠猜”變成了“按局號(hào)拉日志”。如果你想把這個(gè)Demo往深了做下一步可以加斷線重連、叫地主超時(shí)自動(dòng)處理、機(jī)器人托管。這些都是很好的進(jìn)階練習(xí)核心牌局邏輯不用動(dòng)。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
亚洲少妇免费视频\| 91狠狠综合久久久久久| 加勒比综合88| 国产熟女二区| 欧美中文字幕男人天堂久久精品| 国产精品免费日韩| 亚洲精品自拍| 久9爱经典视频| 中文字幕少妇色 | 精彩国产视频播放1区2区| 无码在线亚洲| 正在播放国产精品一区| 免费AV中文网在线观看| 免费国产视频| 亚洲无线观看久久| 国产精品视频内谢女人| 青青操国产夫妻| 躁躁日曰躁2020| 少妇一线天久久久久久| 岛国小电影| 六月丁香婷| 精品国产乱码久久久久久口爆网站 | 18禁精品网站在线看| 欧美精品69性爱| v91av| 青青草一区二区高清无码视频| 色大香蕉97N| 91在线欧色| 婷婷五月在线视频| 色播丁香| 精品十三区| 黑操B| 九九色图| 狠狠图片青青草| 国产青视频| 97视频观看| 区日韩亚洲乱码av电影| 夜夜 中文视频rt| 操人妻逼91| 日本久久久久久久久| 欧美78p| 天天干天天做| 五十路成人在线视频二区三区| 爱妻综合网| 精品国产综合久久福利,热99这里有精品综合久久,99热这里只有免费国产精品,精 | 330dv亚洲成年视频网| 奸色色 男人天堂 天天射| 婷婷综合网| 欧美很很操视频| 91人妻Pr| 爱爱动态120秒| 少妇二级| 人人操人人摸人人看人人干| 最新国产亚洲精品精品国产亚洲综合| 欧美在线伊人色| 丝袜综合| 蜜桃网熟妇| 午夜经典| 国内偷拍精品一区二区| 波多野结衣一级视频| 国产家庭乱伦网址| 婷婷色色五月天| 香一区二区三区| 91中文精品日韩欧美在线| 亚洲日产专区婷婷| 东京热,男人的天堂| 欧美大的香蕉有线电视视频| 岛国大片国产| 丁香五月婷婷啪啪| 亚洲国产精品久久久久婷婷青年| 97一本大道亚洲一区| 呻吟 欧美 日本 中出| 美女十八禁| 嗯嗯啊啊操我| 中日韩欧美精品无码AⅤ一区二区| 五月婷婷六月激情| 日日夜夜草草草| 亚洲欧美骚| 日韩国产欧美伦理在线| 青青草九九九九九| 久久久久久久| 色yeye成人免费视频| 亚洲色鬼| 后入日本1234| 人妻另类 专区 欧美 制服| 乱伦图av| 青青草乱入乱欲视频在线观看| 久久线上视频免费看| 成人一道本免费视频| 97香蕉碰碰人妻国产欧美| 嗯啊啊啊轻点视频 | 啪啪啪东京| 综合久草| 97综合| 欧美一级做a爰片免费视频| 黄总AV色图| 久久久一区二区三区麻豆| 天天谢天天干| 久久久久日本视| 亚欧美色图| 啪啪啪精品| 91亚洲黑人| 亚洲高清在线se| 人人操我人人干| 亚洲少妇喷视频看| 极品少妇久久久久| 国语av最新自产拍在线观看| 伊人四虎综合| 影音先锋视频在线| 欧美日韩青操| 天堂中文资源在线bt| 殴洲老熟女| 思思久热在线精品66| 久久久网站| 中文字幕日韩情色| 大香网站| 亚洲国产日韩精品久久久| 亚洲中文字幕网| 欧美日韩人妻少妇 一区二区三区| 精品日韩人妻视频| 台湾佬中文娱乐自偷自拍| 国产精品女aA片爽爽视频| 狠狠操狠狠爱| 夜夜天天噜狠狠爱2021| 啊啊啊啊啊啊啊啊啊啊在线观看| 亚洲1区2区三区高清中文字幕| 日逼五月天| 亚洲黄色视频在线观看视频| 操我啊啊啊啊啊| 91一区二区三区蜜桃| 哈哈操电影AV| 日本高清视频xxxx| 亚州综合图片| 蜜乳AV网址| 97久久天天综合色天天综合色电影| 日美免费黄片| 无人区高清电影免费观看一区二区三 www.qmcai2.com | 婷婷AV一区二区三区| 久久噜噜噜精品国产亚洲综合| 中文字幕亚洲永久精品| 欧亚日韩综合精品国产| 精品国产精品一区二区| 99热婷婷一区二区三| 在线日韩视频| dy888午夜老子影视达达兔| 中文字幕二区日韩天堂| 中国一级操逼视频| 女生久久网| 久久国产精品,久久国产| 久久精品国产欧美日韩亚洲欧美日韩中文久久国产一区 | 九九色影院| 午夜欧美精品久久久| 男人天堂.AB| 婷婷视频在线免费观看| 97超碰人妻| 亚州熟妇精品| 黑丝91视频| 国产一区二区三三视频| 91天美免费| 96久久科窝| 青娱乐欧美激情一区二区| 蜜臀久久99'精品久久久| 99视频只有精品| 天天射天天操天天干天天吃2018| 春色综合免费| 亚洲999综合| 91 刺激在线| 国产精品毛片?v一区二区三区 | 色激情五月天| 天天摸夜夜添无码小视频| 婷婷人妻激情| 97AV在线免费观看| 婷婷三区| 九色97| 国产精品香蕉热久久新品| 天天干夜夜鈤| 国产日韩中文字幕欧美| 啊啊啊不要嗯嗯在线观看| 天天日B狠狠操| 丰满的三级少妇欧美久久久| 欧美的性爱网站免费| 自拍啪啪视频| 欧洲一区二区三区四区在线观看| 日本一久是| 97干色天堂| 婷婷午夜| 激情丁香五月婷婷| 日本午夜精品理论片A级APP发布| 国产隔壁老王影院在线| 午夜男女爽爽爽影院视频| 91精品91久久久久77777| 亚洲 欧美 小说| 五月丁香六月激情综合| 涩五月婷婷| 国产亲戚伦亲在线| 日本东京热加勒比久久| 久久免费99精品久久久久久| 蜜臀久久99精品久久久| 超碰97综合| 九久久精品| 色综合99999| 欧美少妇内射| 有码人妻系列| 精品999日本| 欧洲亚洲人妻无码中字久久三区四区| 国产人妻精品久久久一区二区三区 | 成人av免费观看| 丝袜美腿制服人妻二区中文字幕| 亚洲精美粉嫩嫩泬在线观看| 国产美女裸体秘 永久无遮挡| 家庭乱伦麻豆| 嫩呦国产一区二区三区AV| 久久久久久久强迫| 国产精品分类在线观看| 日韩免费福利在线观看| 一个色导综合| 先锋色眉乱伦资源| 亚洲aV无码成人在线观看| 久久国内| renqi久久久久久久久久久久| 久久久久成人蜜桃精品| 久草视频制服诱惑| 锕锕好爽 死我在线观看| 最新9久久久9免费视频| 高潮9999外国| 91情色| AV一区观看| 老熟女乱子伦中文字幕一区二区 | 亚洲日韩狠狠撸视频| 噜噜瑟| 水滴偷拍| 在线观看亚洲专区| 少妇国产不卡| 秋霞福利网| 国内外毛片在线观看| 0755午夜福利视频| 日本十八禁免费看污网站| 人人操人人摸人人看人人干| 伊人AAA| 亚洲AV乱码专区国产噜噜亚洲| 插老姨肥穴| 日韩精品影视| 色汉综合| 全免费a敌肛交毛片免费| 欧美日韩第一页| 欧美日韩m| 亚洲 欧美 小说| 97久久国产亚洲精品超碰热| 天天看天天日| 麻豆啪啪啪视频| 亚洲不卡AV在线| 中文在线久久字幕| 免费视频观看60秒| 视频黄色国产一级| 中文字幕老熟妇黄色视频| 最新精品久久蜜桃| 加勒比综合| 日韩人妻 中文字幕| 久久99热这里只频精品6学生| 日韩中文字幕熟妇人妻| 欧美偷| 乱伦一二三区| 中文字幕一区二区三区蜜臀| 这里只有精品97| 330dv亚洲成年视频网| 天天狂操夜夜狂日| 美女极品一区二区三区| 婷婷国产精品九区| 国产91 丝袜在线播放| 狠狠中文字幕| 蜜臀亚洲中文| 日本淫乱女一区二区三区视频| 91丨熟女丨丰满熟女| 国产精品2020| 欧美综合网在线| 操逼逼无码| 伊人一区二区三区| 秋霞操逼片| 亚洲日韩一区电影| 超碰人妻久久| 亚洲熟妇自偷自拍另欧美| 久久禁| 亚洲欧美在线观看免费| 97日视频| 精品成人无码| 熟妇艹鸡八| 色色毛片| 欧美综合第一| 亚洲综合另类小说色区亚洲成av人片在www | 国产亚洲一黄| 97干97色| 天天日日日射| 日韩成人精品| 蜜桃色院一区久久 | 夜夜嗨一区二区三区三州加勒比| 91高清无码下载| 日本超碰97日韩精品人妻| 午夜视频久久久久一区| 青青草色情网站视频| 偷拍 欧美 日韩| 嗯嗯,啊啊,国产精品| 97爱综合| 操逼短片| 色情综合网| 黑人综合网| 嗯嗯嗯啊啊啊在线免费观看| 色呦呦国产精品免费看| 97爱亚洲综合色| 欧美一级特黄淫片在线观看| 成人一级二级| 超碰激情808| 人人做,人人操,人人摸| 久久精品视| 欧美人妻一区| 日夜伊人网| 亚洲天堂另类美腿| 蜜臀AV秘一区翔田千里| 另类老少妇| 久久久网站| 69天堂| 午夜精品久久久久| 911粉嫩人妻| 久久久精品网| 亚洲精品97中文字幕| 小情侣高清国产在线视频| 久久老熟女| 91丝袜美女| 黄色视频60分钟| 少妇激情AV| 亚洲精品一区中文字幕乱码| 奇米四色影视777久久久| 日韩人妻丝袜美腿中文| 亚洲美乱| 欧美日韩一区二区三区四区蜜桃| 欧美色图20p| 殴洲老熟女| 色综合久| 性爱免费视频成人| 青青草久草| 啊嗯嗯啊好大好爽| 国产精品久久久久绯色| 午夜福利成人免费视频| 精品人妻中文字幕高清| 日韩无码服务区| 久久久99久9| 人人干人人操人人..com| 精品蜜乳AV免费观看| nuu12国产麻豆精品| av优播| 国产第25页在线观看| 中文字幕蜜乳av| 日本中文字幕熟妇| 久久免费精品96| 黄色网址久久精品欧美喷水| 五月丁香成人网| 色狠狠 - 百度| 日韩黄片影院| 欧美资源| 蜜臀网 一区| 精品九九淫乱男| 天天干2区3区| 日韩另类色图| 日韩久久三区| 成功精品影院| 9久久精品| 欧美人与性动交a美精品| 1769一区| 浓厚中出中文字幕在线| 日产欧美电影一区二区三区| 黄片www视频免费| 人妻丝袜一区二区三区在线| 四虎影视国产精品| 蜜桃网熟妇| 亚洲情色一区二区三区| 少妇人妻无码| 精品视频专区| 日韩欧美偷拍美女视频| 亚洲男人的天堂AV| 有码色中文字幕在线观看| 操穴国产| 国产美女激情| 秋霞鲁丝午夜无码一区二区三| 国产十八禁视频| 热久日综合| 2019AV天堂| 日本精品国产视频| 台湾大香蕉99热| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | www.久久| 超碰国产情侣自拍网| 亚洲国产综合久久久性感熟妇| 91N欧美| 欧美嗯啊……在线观看视频免费| 91丝袜美腿网站| 男人干美女| 欧美A√综合网 | A级国产欧美激情在线| 亚欧美色| 欧美一级黄色免费专区| 欧美一级黄片视频在线| 国产区91柔拿会所技师| 亚洲激情综合| 爆乳免费黄网站| 蜜臀久久在线视频| 欧美日韩精品久久久久东北老熟妇| 超碰色美女| 久久精品国产亚洲粉嫩| 天天懆天天日| 欧美黄色片AAAAA| 天天爽爽爽爽| 激情视频一二三| 黄页网站成人免费| 欧美gv在线观看| 无码精品人妻一区二区三区妖精| 日本精品成人无码| 精品国产污一区二区三区| 欧美激情片一区二区| 试看60秒| 操操操五月天婷婷丁香影院| 午夜国产成人福利视频| 色爱综合网欧美| 无卡一区=区| 天天综合网91| 久久性爱网站| 亚洲欧美爆| 熟女熟妇伦久久影院毛片一区二区| 亚洲天堂加勒比| 91丨国产丨白浆秘 洗澡动漫| 天天操夜夜嗨| 亚洲综合五月天| 懂色AV中文| 日日玩天天干| 操婢日韩| 人妻少妇精品一区二区三区| 久久综合久色欧美综合狠狠| 亚洲成人贴图| 九九色精品| 一区二区 电影 亚洲| 97亚洲综合在线| 超碰人人操97碰| 日本天天色| 老司机午夜精品福利视频一区二区| 久久久久夜夜夜夜| 久久久久久AV无码免费网站| 蜜桃色院一区久久 | 午夜无遮挡男女啪啪视频| 亚洲中文字幕网| 亚洲第一二区另类图| 999999精品| 3p国产欧美99热| 九九自拍伦理| 国模私拍一区二区三区神乳| 97久久精品亚洲| 日本久久久精品电影| 少妇高潮流水av免费| 97中文超碰| 精品人妻高清麻豆av| 隔壁邻居波多野结衣中文字幕 | 操一对老熟妇爽上天视频| 久久av成人无码免费| 日韩AV色图| 国产精品九九九| 五月婷婷深深爱| 清纯唯美综合亚洲| 五月天久久久| 天天干18禁| 欧美一级色| 中国韩国明星一极片一区乱码毛片人妻熟女一区二区三区 | 在线国产探花| 四虎精品亚洲| 99久热| 欧色网址| 天天色悠悠激情| 国产久久久久久| 人妻碰碰碰碰碰碰| 欧美黄色手机在线观看| 日少妇亚洲版| 国产日韩区| 新精精品久久精品| 亚洲免费人妻在| 91中出在线| 丁香五月色| 麻豆美女丝袜人妻中文| 岛国小电影| 男人的天堂午夜av| 北野未奈加勒比av| 亚洲精品 大香蕉| 99久久精品国产系列| 综合网亚| 亚洲欧美日韩精品久| 久草电影网| 亚洲情色91| 国产精品露脸在线观看| 操老熟女AV| 99精品久久| 日韩欧美性爱电影在线观看| 亚洲区限制级| 五月天激情四射| 午夜小电影在线插入淫高潮| 亚洲AV无码久久精品蜜桃小说| 熟女五十路一区二区三| 理论久久婷婷网8| 九九九网页| 日本日逼高清| 97视频在线观看免费高清| 国产精品久久久视频| 色在线亚洲视频www| 伊人网一本| 九九热九九热| 日韩欧美国产高清视频| 韩国一级做a久久久久| 蜜臀久久久国产| 激情五月婷婷综合| 操操操日本的逼| 免费视频一二三区| 欧美极品少妇| 免费9 1久久| 色婷婷综合网站| 偷拍亚洲熟女视频播放| rion磁力链接| 9997se| 国产一级久久久| 婷色五月天| 免费在线黄片视频| 边做饭边操逼逼| 91痴汉| 欧美大片天天看| 夜夜嗨AV一区天天| **一级毛片国产| 欧美黄色片在线播放| 酒色综合网| 亚洲少妇免费视频\| 天天操夜夜操狠很操| 精品久久97观看在线视频| 夜夜操一区二区| GVH-003 母子姦 青木玲-麻豆视频,麻豆视传媒短视频网站入口,麻豆视传媒官网直 | 一区二区视频在看| 一区二区不卡免费| 黄色片G G G| 色狠人在线99| 夜夜操91744565| 色色操| 国产成人精品日本亚洲语言| 欧美亚洲尤物久久| 大香蕉一区二区在线观看.| 精品人妻一区二区免费蜜桃视频| 麻豆一区二区三区在线看| 国产欧美后入| 青青草久久在线| 99re99视频在线免费观看| 2025亚洲男人天堂| 欧美永久激情一区二区| 妇女视频网站| 青草香蕉网| 九九成人精品| 欧美国产一区二区三区麻豆传媒 | 精品中文字幕第一页| 大香蕉免费3| 操逼无码操逼| 国产51色综合久久免费| 不卡一区二区日本视频| 亚洲成熟国产精品美女| 亚洲国产成人精品无码专区| 国产精品香蕉热久久新品| 日本欧美亚洲高清在线看| 高清无码 国产精品| 亚洲成?V人片在线观看福利| 中文自拍欧美影视| 9久热| 日本高清电影欧美色图| 人人喜人人妻| 欧美亚洲厕所精品偷拍91| 九九热在线精品视频| 91男同| 日韩欧美麻豆 | 综合欧美日本三级| 色婷婷综合久久久久中文国产精品一区中文字幕,国产福利电影一区二区三区 | 免费中文在线| 久久久一级| 性色avv| 98精品国产乱码久久久久久| 超碰偷拍| 日韩在线国产字幕| 26uuu性| 综合网色| 在线视频一区二区传媒| 午夜精品久久久99热蜜桃的功能特点| 国产精品伦理| 欧美熟妇成人一区二区| 欧日a| 亚洲少妇色| 色大香蕉97N| 一本色道人妻久久| 国产传媒午夜理伦精品| 欧美性爱在线无码| 欧美人妻二区三区| 亚洲图片偷拍欧美| 久9re热视频这里只有精品| 免费观看国产小粉嫩喷水精品午| 性爱乱伦一区| 动漫片子网站3黄| 亚欧美综合| 国产精品直播在线观看直播| 色青青久久影视| 男人天堂站| 亚洲天堂久久| 中文字幕国产| 荡小穴在线观看| 台湾佬中文娱乐网久久久久久久久久com | 久操97| 国产av美女被艹的乱叫| 欧美欲色| 亚洲情色视频| 精品久久人妻成人网| 亚洲精品欧美专业| 人人操人人肉久久精品| 亚洲黄色网址视频| 东北老女人的激情视频| 亚洲图片第一页| 一级久久性爱视频| 97超视频在线观看| 你懂的在线观看区国产| 久久黄黄| 亚洲欧美伦综合| 蜜乳性色无码专日粉嫩骚逼AV| 青青草亚洲一区| 97这里有精品| 精品久热| 精品国产乱码久久久影院| 一级日本牲交大片好爽在线看| 日韩偷拍色图| 性一级黄色录像片网站导航 | v91av| 熟女突然公开看18禁影片| 男人的天堂在线| 亚洲国产一区二区日韩专区| 亚洲激情 欧美色图| 97干97色| 国产不卡片| 91九九| 精品久久久九九九孕妇| 亚洲熟女av中文字幕| 亚洲激情综合| 91bbbbbb| 久久色人体| 女人综合网| 91人人爽人人爽| 日本综合色图| 人妻久热在线| 男女做爰猛烈动高潮A片免费应用 少妇厨房愉情理伦片bd在线观看 不卡中文字幕aⅴ在线 | 亚洲毛片久久| 天天色综合图片| 97色亚洲| 校园春色亚洲欧洲| 性色av大全| 高跟伊人julia ann| 久久五月天婷婷丁香中文字幕| 九热大香蕉| 国产成人欧美一区二区三区的国产| 天天内射| 人人考人人摸人人干| 高清无码91| 天美国产精品| 欧美一二三级精品在线| 98精品国产乱码久久久久久| 久久久精品视频免费观看| 日韩欧美久久婷婷网站| 99精品无码| 亚洲一区日韩精品中文字幕| 久久日本熟女精品一区| 黄aaaaaaaaaaaaaaaaaa色网站| 正宗无毛一线天嫩逼| 欧美日韩丝袜 | 国产精品高潮久久AV| 男人a天堂手机在线版| 五月天AV资源| 区一在线观看| 亚洲高清无码AAA久久久精品| 日本黄色精品| 97色色色综合网站| 熟女人妻一区二区三区| 超碰在线一区二区三区| 四季AV一区二区凹凸精品小说| 日韩不卡a级视频专区| 美女网站91| 60秒免费小视频| 日韩啪啪网| 中文字幕黄片在线| 夜夜久久久| 熟女色图在线| 天天综合网站| 亚洲91在线播放影院| 超碰色97| 久久6热精品99视频| 五月天激情婷婷| 污污汅18禁网站在线永久免费观看 | 欧美传媒| 亚洲人妻爽爽爽| 欧美伦乱爱| 国产精品麻豆成人AV艾秋| 亚洲91在线播放影院| 天天射日日干| 欧美久久人体| 亚洲成人妻日韩在线| 天天欧美色| 国产福利第一视频| 国产欧美日韩一区二区三区| 亚洲综合第一页| 青青草依人大香蕉| 久久久久斤小| 亚洲综合影片| 国产亚洲 中文欧美久久| 操逼逼无码| 一线黄色免费性爱片| 午夜小电影在线插入淫高潮| 国产精品白丝www| 欧美激色| 射丝袜大香蕉| 今日头条成人一区二区三区四虎精品| 97中文天堂| 日韩成人精品中文字幕| 一起草精品人妻| 狠狠操夜夜| 国产在线激情视频| 亚欧毛片基地国产毛片基地| 精品91| 久久久久久久久一区二区三区| 99999这里都精品| 国产人妻一区二区三区欧美毛片| 蜜桃中文字日产乱幕4区| 欧美九9 9 9| 操人91| 国产激情视频在线观看| 牛牛aV| 留下AⅤ黄色片| 亚欧高清在线| 免费av大片| 亚洲一区二区性爱电影| 亚洲成人性爱在线观看| 精品在线观看视频在线| 伊人五月天激情| 在免费jIzzjIzz在线视频| 波多野结衣先锋影音| 国内毛片婷婷六月色| 欧美另类精品xxxx| 成人性爱全视频观看| 333kkkk·亚洲com久久| 欧亚性爱视频免费看| 亚洲AV无码国产精品久久久久| 欧美成人性爱视频免费观看| 嫖老熟女A片一二三区| 日韩欧美经典在线观看| 婷婷伊人网| 天天操夜夜操| 高树玛利亚无码流出| 97超碰热线| 四虎在线播放| 91在线丝袜| 亚洲交性| 亚洲一区中文精品| 操逼www.| 超碰在线人妻| 丝袜制服字幕在线| 色大香蕉97N| 男人的天堂三级| 亚洲另类春色| 中文字幕国产| 婷婷五月天av| 91 国产丝袜在线放观看| 成人精品一区二区三区| 午夜亚洲| 看免费一级在线播放毛片| 国产欧美成人第一页在线观看| 8050无码八戒| 日韩专区数据列表-第3230页-精品国产一区二区三区香蕉 久久99熟女人妻中文字 | 国产高清亚洲日韩一区| 国产在线视频二区| 偷窥自拍亚洲天堂网爆| 人妻精品综合中文字幕在线| 欧美大片一区二区三区| 清纯唯美综合| 日本欧美韩国国产在线| 日本污ww视频网站| 中文字幕乱碼在线| 欧美色91| 国产对白刺激视频| 天天干天天做| 新精精品久久精品| 资源新线在线天堂| www.av在线视频| 好吊色在线观看| 加勒比色综合| 亚洲春色一区二区三区| 欧亚在线视频| 密臀视频一区二区三区| 不卡视频一区蜜桃视频 | 欧美国产操逼| 97香蕉网| 婷婷激情综合网| 亚洲一区二区 麻豆传媒| 熟女人妻精品一区二区视频 | 97久操| 黄骗免费| 综合网亚| 欧美一区二区男人天堂| 成人午夜无码视频| 校园春色中文字幕AV| 欧美狠狠干| 亚洲啪啪性视频| 欧洲精品久久| 久草精品国产99| 嗯嗯嗯好爽| 蜜臀va69| 人人操人人叉人人插人人| 亚洲色欲一区二区三区| 欧美美女视频| 婷婷丁香久久| 91精品操美女| 99久久精品无码一区二区| 麻豆精品A片免费观看| 2017天天拍大香蕉| 91精品91久久久中77777| 亚洲第一男人天堂| 丝袜熟女一区二区三区| 99精品人人爽| 日韩精品人妻一| 夜夜騷av、一區二區| 又粗又长又大国产不卡| 97电影院超碰| 97色在线视频| 天天综合日韩网| 啊啊啊啊好爽好舒服一区二区易域| 无码日韩网站| 国产又大又粗又长视频| 九九探花视频在线观看| 精品妇操一区二区三区| 久久精品中文字幕无码l| 欧美色日本| 国产特级毛片AAAAAA高潮流水| 国产熟妇一区二区| 伊人丁香五月婷婷| 久久综合av| 午夜精品探花| 欧美最婬乱婬爆婬牲视频| 久草免费在线一区二区| 蜜桃午夜视频一区二区 | 日本高清一本二本免费不卡| 入口操逼网站| 国产91美女视频| 婷婷在线播放| 亚洲伊人久久综合97| 神马午夜久久久| 国产操操日韩三级黄| AV色五月| 亚洲五月丁香花狠狠干一区二区三区| 精品人妻av区天天看片| 亚洲最大的黄色电影网站。| 日韩免费三级黄片电影| 中文字幕第23区| 性爱av网站| 欧美懂色综合网| 欧美精品91| 国产92麻豆天美精品色欲5| 在线洲亚线| 色穴精品| 日韩欧美午夜视频在线| 亚洲av资源| 国产传媒美日韩av| 欧亚乱色熟女一区二区| 国产精品农村妇女| 欧洲乱码视频| 天美麻花大全视频| 肏逼视频日本| 中文日韩欧美熟| 亚洲无套久久嗯嗯| 天天做日日做| 久久久久久久| 国产成人天堂| 亚洲欧美激情另类色图| 色欲无码人妻日韩欧美精品| 超碰超碰欧美| 日本免费中文字幕在线| 综合亚洲欧美| 色超碰综合| 黄色网址久久精品欧美喷水| 人人艹亚洲| 人人操人人肉久久精品| 亚洲日产专区婷婷| 亚洲天堂综合AV| 中国zzijzzijzzwww精品| 欧美色乱| 欧美成人国产精品| 午夜福利久久久噜久噜久久综合| 热99这里只有精品| 日本人妻中文字幕精品| 亚洲黄色AV电影| 龙兴卡官方查询| 亚洲中文字幕妇伦久久| 婷婷五月天激情网| 约操熟妇| 欧美日韩啪啪电影| 91天天综合日韩欧美| 久热99999| 日欧毛片久久| 日韩AV中文字幕电影| 色综合婷婷| 国产精品婬乱一级毛片彝族| 久久久久亚洲熟妇熟女| 2017天天插| 亚洲91射| 中文字幕一区二区三区蜜桃视频| 精爱久久| 无码99| 天天做天天爱| 在线国产探花| 强奸乱伦资源| 啪啪免费| 国产绿奴视频在线观看| 在线观看亚洲成人精品| 精品国产乱码久久| 花花AV导航| 91精品人妻一品二品三品| 伊人久日| 国产AV线| 无卡一区=区| 亚洲91大片| 精品美女久久一二三| 国产二区三区粉嫩在线| 又摸又舔在线观看网站| 亚洲淫乱骚妇AV| 久久综合日韩亚洲欧美| 999日韩中文精品观看视频。| 婷婷丁香六月| 婷婷五月天综合网| 91 刺激在线| 久久草草欧美精品| 超碰97起碰| 蜜臀久久99精品久久久老,,| 精品一区二区三区蜜桃臀赵总| 五月丁香六月激情综合| h在线看免费版在线看| 日韩熟妇二区| 天天操av懂色| 美女淫穴| 伊人久久亚洲中文字幕不卡| 99精品人人爽| 婷婷探花久久精品一区| 欧美日韩小说| 蜜臀AV午夜精品久| 熟女探花啪啪| 一级二级三级黑人无码| 亚洲国产婷婷在线播放| 日本高清有码网址视频| 黄片在线免费在线观看| 水野优香在线观看| 超碰国产情侣自拍网| 国产九区| 夜夜高潮夜夜爽国产伦精品| 亚洲欧美在线丝袜| 欧美性爽xyxOOOO| 欧美区亚洲区偷拍区| 欧美一级久久久久久久大片动画| 久久激情亚洲精品无码?V| 久久HD| 日韩 人妻 精品| 欧美男人亚洲天堂| 成人AV在线网站| 搡老女人老熟女91| 国产在线激情视频| 亚洲av无码成人精品国产| 欧洲无码一区二区| 乱久久久| 激情欧美97| 国产a片操逼| 秋霞视频一区二区 | 亚洲欧美日韩制服另类| 亚洲最新av无码成人精品区| 熟女突然公开看18禁影片 | 亚洲激情在线观看一区| 午夜福利成人免费视频| 亚洲aw毛茸茸在线| 色哟哟精品1精品2| 国产拍偷精品网站| 久久久久国产一区二| 一区二区久久天天干狠狠| 天天操美美| 日本精品五区| 网页导航五月天免费一二三区| 熟女人妻av在线资源,黄色的资源| 好好的日:com久久九九| 国产精选视频| 国产精品一区午夜福利| 日韩有码免费视频| 国产乱码久久久久久| 国产精品香蕉| 99热这里只有精品地址| 成人综合网 欧美| 日韩欧美中文字幕搭讪巨乳美人妻视频| 超碰精品国产无码| AV中文在线| 98超碰日本| 日韩欧洲操屄视频| 日日狠狠久久偷偷色综合免费| 伊人久久亚洲中文字幕不卡| 国产深夜福利| 影音先锋国产精品| 亚洲一区二区 麻豆传媒| 黑人娇小av在线播放| 一区二区娱乐网站| 亚洲天堂日本| 亚洲āv网址在线观看| 五月天综合网| 久草久日| 国产精品女久久久久av爽| 日韩欧亚太美不卡| 伊人操| 99热久| 精品日韩产品在线,日韩在线不卡视频,欧美日韩免费专区/久, | 丁香五月综合| 日韩不卡码| 岛国A V在线免费看| 久操视频免费在线观看| 久9九综合在线| 五月丁香婷婷色| 日韩BBN| 大地资源在线观看中文第二页| av线电影| 欧美不卡二区| 欧美色图人妻| 日韩国产不卡在线视频| 日韩啪啪啪视频| 国产一级137片内射麻豆| 久久精品视频28| 伊人操你| 欧美白嫩女HD| 国产精品爽爽v| 在线观看午夜婷婷久久久久清性观看| 国产精品爱欲| 精品一区二区三区四区外站| 无码人妻精品一区二区中文| 日欧毛片久久| 伊人网综合在线视频| 国产成人精品一区| 91痴汉| 成人热久久精品| 明星性猛交ⅹxxx乱大交| 国内精品不卡无毒99999| 久96热在线观看视频| 九一综合精品视品av| 人人做,人人操,人人摸| 超碰97最新人妻| 人妻一区视频| 99久在线精品99re8| 久久久久婷婷| 中欧人妻丝袜中文字幕| 亚欧美天堂在线| 成 人片 黄色大片| 青青青草伊人精品| 午夜精品视频777| 91bbb| 日韩中文字幕av在线播放| 丰满人妻无码一区二区三区| 九热超碰| 久久人妻丝袜一区二区三| 国产操逼网站亚洲一级黄色| 97久久超碰国产网站| 青椒国产97在线熟女| 亚洲天堂少妇| 色香阁在线| 亚洲三区视频| 午夜美女诱惑电源网| 伊人影院在线理论播放| 久草国产在线视频| 欧洲综合色| 欧美狠狠弄| 在线精品福利免费播放| 91性情| 国产青青美女玩逼视频| 国产免费久久久久| 婷婷超| 天天热精品| 久久久久久中文字幕中文字幕最新| 大香蕉www.超碰| 欧美成人精品一区| 久久中日麻豆| 天天干少妇| 亚洲成人免费中文字幕| 先锋女优在线观看视频| av一区二区三区四区五区久草臀| 伊人色综合网电影| 无码一区免费在线不卡| 怡红院亚洲怡春院av| 色综合中文字幕不卡| 亚洲AV无码国产精品久久久久| 懂色Av| 四虎免费视频| aaa淫乱视频| 婷色五月天| 日韩人妻中文视频| 国产精品成人AV片免费看网站| 青青草女人天天干| 91天天综合网,天天综合网| 色综合色色| 久久久国产亚洲精品系列| 欧美亚洲中文| 久久精品操| 国产乱码久久久久久| 日本女厕偷拍| 中文字幕高清20页视频| 天天干天天操天天干天天操| 亚洲国产一级黄色视频| 大香蕉人妻久久| 精品无码产区一区二| 亚洲色性情三级| 在线观看AV不卡| 五月丁香| 日本午夜久久电影| 国产人伦a片信息免费片| 亚洲人妻中文在线视频| 97天天综合| juliaann欧美丝袜办公室| 亚洲91射| 国产女主播视频在线观看| 好屌色综合| 日韩钢筋无码高清啾啾啾| 色哟哟国产精品免费网址| 五月天激情小说| 欧美一级A片在线看视频性色| 国产精品无套内谢| 逼操网站| 黄色电影在线播放综合网站| 丁香五月av| 欧美AAAA黄片| 国产精品96| 九九九999久久久网站| 97伦乱| 亚洲人综合| 破处bbq| 加勒比性爱成人在线| 午夜AV污污污| 色九九综合AV| 欧美一品道| 青青草中日韩在线| 欧美亚洲综合999| 无码操逼天堂| 中文字幕免费看| 久久亚州大香蕉| 九九九偷拍| 欧美性夜| 超碰78| 超碰在线欧美性爱激情| 操屄日韩| 波多野结衣一级视频| 手机在线A片| 國產尤物AV尤物在線觀看| 国产精品一二三在线看| 免费操逼视频下载| 亚洲精品久久久久久久蜜桃臀| 99久在线精品99re8热| 嗯嗯啊中文字幕|