|
|
@@ -0,0 +1,389 @@
|
|
|
+using System;
|
|
|
+using System.Collections;
|
|
|
+using System.Collections.Generic;
|
|
|
+using UnityEngine;
|
|
|
+using Newtonsoft.Json;
|
|
|
+
|
|
|
+public class YejiHuntGameMode_OnlinePK : YejiHuntGameMode, ChallengeGameModeLocalPK
|
|
|
+{
|
|
|
+ public int currentPlayerIndex = 0; // 双人0和1
|
|
|
+ float singleShootReadyTime = 30f;
|
|
|
+ float singleShootReadyTimeMax = 30f;
|
|
|
+ public YejiHuntGameMode_OnlinePK(GameMgr gameMgr) : base(gameMgr) {
|
|
|
+ onlineHelper = new OnlineHelper(this);
|
|
|
+ hunterGamePlayerScoreCounter = new HunterGamePlayerScoreCounter(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ public override void Start()
|
|
|
+ {
|
|
|
+ onlineHelper.InitSocketPlayer(OnStart);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnStart() {
|
|
|
+ banCreateAnimal = onlineHelper.IsCopyHost();
|
|
|
+ banOnBowArrowShootOut = onlineHelper.IsCopyHost();
|
|
|
+ Yeji.InitPreHeights();
|
|
|
+ SetLevel(5);
|
|
|
+ AddHuntGameView();
|
|
|
+ this.gameMgr.transform.Find("HunterGameView_LocalPK").gameObject.SetActive(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public override void onBowShoot() {
|
|
|
+ if (onlineHelper.IsCopyHost()) {
|
|
|
+ onlineHelper.socketPlayer.UploadPKGameData("onBowShoot", "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public override bool DoNextShoot() {
|
|
|
+ if (onlineHelper.IsCopyHost()) {
|
|
|
+ onlineHelper.socketPlayer.UploadPKGameData("DoNextShoot", "");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ foreach (var item in Yeji.yejiSet) {
|
|
|
+ if (item.onlineHandler.onDoNextShootWillDestroy) {
|
|
|
+ GameObject.Destroy(item.gameObject);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ bool canDo = base.DoNextShoot();
|
|
|
+ if (canDo) {
|
|
|
+ NextPlayerFinal();
|
|
|
+ }
|
|
|
+ return canDo;
|
|
|
+ }
|
|
|
+
|
|
|
+ void AddReadyView()
|
|
|
+ {
|
|
|
+ GameObject view = Resources.Load<GameObject>("Prefabs/Views/PKGameReadyView_Challenge");
|
|
|
+ GameObject o = GameObject.Instantiate(view);
|
|
|
+ PKGameReadyView_Challenge script = o.GetComponent<PKGameReadyView_Challenge>();
|
|
|
+ script.currentPlayerIndex = currentPlayerIndex;
|
|
|
+ }
|
|
|
+
|
|
|
+ void NextPlayerFinal() {
|
|
|
+ NextPlayer();
|
|
|
+ BanBowReady();
|
|
|
+ AddReadyView();
|
|
|
+ }
|
|
|
+
|
|
|
+ void NextPlayer() {
|
|
|
+ currentPlayerIndex++;
|
|
|
+ currentPlayerIndex %= 2;
|
|
|
+ singleShootReadyTime = singleShootReadyTimeMax;
|
|
|
+ onlineHelper.roundID++;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override void Update() {
|
|
|
+ if (!onlineHelper.IsMyPlayerInited()) return;
|
|
|
+ if (!onlineHelper.IsMainHost()) return;
|
|
|
+ if (!onlineHelper.IsMyPlayerRunning()) return;
|
|
|
+ OnUpdate(Time.deltaTime);
|
|
|
+ }
|
|
|
+
|
|
|
+ void OnUpdate(float dt) {
|
|
|
+ if (gameMgr.gameOver || pauseTimeCounting) return;
|
|
|
+ if (this.time > 0) {
|
|
|
+ this.time -= dt;
|
|
|
+ } else {
|
|
|
+ this.time = 0;
|
|
|
+ AnnounceGameOver();
|
|
|
+ }
|
|
|
+ if (gameMgr.gameOver || pauseTimeCounting) return;
|
|
|
+ singleShootReadyTime -= dt;
|
|
|
+ if (singleShootReadyTime <= 0) {
|
|
|
+ //切换玩家
|
|
|
+ ArmBow.ins.readyShoot();
|
|
|
+ NextPlayerFinal();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public override void FrameUpdate() {
|
|
|
+ onlineHelper.OnFrameUpdate();
|
|
|
+ }
|
|
|
+
|
|
|
+ //localPK interface
|
|
|
+ public int GetCurrentPlayIndex() {
|
|
|
+ return currentPlayerIndex;
|
|
|
+ }
|
|
|
+ public (float, float) GetSingleShootReadyTime() {
|
|
|
+ return (singleShootReadyTime, singleShootReadyTimeMax);
|
|
|
+ }
|
|
|
+ HunterGamePlayerScoreCounter hunterGamePlayerScoreCounter;
|
|
|
+ public HunterGamePlayerScoreCounter getHunterGamePlayerScoreCounter() {
|
|
|
+ return hunterGamePlayerScoreCounter;
|
|
|
+ }
|
|
|
+
|
|
|
+ //###------------
|
|
|
+ //### 联机部分
|
|
|
+ //###------------
|
|
|
+
|
|
|
+ public class SyncLogicData {
|
|
|
+ public int roundID;
|
|
|
+ public int currentPlayerIndex;
|
|
|
+ public float singleShootReadyTime;
|
|
|
+ public int animalCount = 0;
|
|
|
+ public int arrowCount = 0;
|
|
|
+ public float time = 60;
|
|
|
+ public int[] hitScores;
|
|
|
+ public bool gameEnd = false;
|
|
|
+ public SyncLogicData Input(YejiHuntGameMode_OnlinePK src) {
|
|
|
+ roundID = src.onlineHelper.roundID;
|
|
|
+ currentPlayerIndex = src.currentPlayerIndex;
|
|
|
+ singleShootReadyTime = src.singleShootReadyTime;
|
|
|
+ animalCount = src.animalCount;
|
|
|
+ arrowCount = src.arrowCount;
|
|
|
+ time = src.time;
|
|
|
+ hitScores = src.getHunterGamePlayerScoreCounter().hitScores;
|
|
|
+ gameEnd = src.gameMgr.gameOver;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ public void Output(YejiHuntGameMode_OnlinePK dest) {
|
|
|
+ dest.onlineHelper.roundID = roundID;
|
|
|
+ dest.currentPlayerIndex = currentPlayerIndex;
|
|
|
+ dest.singleShootReadyTime = singleShootReadyTime;
|
|
|
+ dest.animalCount = animalCount;
|
|
|
+ dest.arrowCount = arrowCount;
|
|
|
+ dest.time = time;
|
|
|
+ dest.getHunterGamePlayerScoreCounter().hitScores = hitScores;
|
|
|
+ dest.onlineHelper.gameEnd = gameEnd;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ OnlineHelper onlineHelper;
|
|
|
+ public class OnlineHelper {
|
|
|
+ YejiHuntGameMode_OnlinePK gameMode;
|
|
|
+ public OnlineHelper(YejiHuntGameMode_OnlinePK gameMode) {
|
|
|
+ this.gameMode = gameMode;
|
|
|
+ }
|
|
|
+ public SocketPlayer socketPlayer;
|
|
|
+ public int myPlayerIndex = -1;
|
|
|
+ public bool IsMyPlayerInited() {
|
|
|
+ return myPlayerIndex >= 0;
|
|
|
+ }
|
|
|
+ public bool IsMyPlayerRunning() {
|
|
|
+ return myPlayerIndex == gameMode.currentPlayerIndex;
|
|
|
+ }
|
|
|
+ public bool IsMainHost() {
|
|
|
+ return myPlayerIndex == 0;
|
|
|
+ }
|
|
|
+ public bool IsCopyHost() {
|
|
|
+ return myPlayerIndex > 0;
|
|
|
+ }
|
|
|
+ public int roundID = 0;
|
|
|
+ public bool gameEnd = false;
|
|
|
+
|
|
|
+ public void InitSocketPlayer(Action successCallback) {
|
|
|
+ if (GameObject.Find("SocketPlayer") == null) {
|
|
|
+ PKMatchingView.MoniMatchForTestInGameScene(() => {
|
|
|
+ myPlayerIndex = GlobalData.playerIndexInRoom;
|
|
|
+ if (successCallback != null) successCallback();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ myPlayerIndex = GlobalData.playerIndexInRoom;
|
|
|
+ if (successCallback != null) successCallback();
|
|
|
+ }
|
|
|
+ socketPlayer = GameObject.Find("SocketPlayer").GetComponent<SocketPlayer>();
|
|
|
+ socketPlayer.onReceivePKGameData = onReceivePKGameData;
|
|
|
+ AutoSwitchBanUserControlBow();
|
|
|
+ }
|
|
|
+ Quaternion bowTargetQua;
|
|
|
+ bool hasBowTargBtQua;
|
|
|
+ void onReceivePKGameData(string key, string data) {
|
|
|
+ if (!IsMyPlayerInited()) return;
|
|
|
+ if (key == "logic") {
|
|
|
+ SyncLogicData syncLogicData = JsonConvert.DeserializeObject<SyncLogicData>(data);
|
|
|
+ syncLogicData.Output(this.gameMode);
|
|
|
+ AutoSwitchBanUserControlBow();
|
|
|
+ }
|
|
|
+ if (key == "bow") {
|
|
|
+ if (!IsMyPlayerRunning()) {
|
|
|
+ string[] quaStr = data.Split(',');
|
|
|
+ if (quaStr.Length == 6) {
|
|
|
+ bowTargetQua.x = float.Parse(quaStr[0]);
|
|
|
+ bowTargetQua.y = float.Parse(quaStr[1]);
|
|
|
+ bowTargetQua.z = float.Parse(quaStr[2]);
|
|
|
+ bowTargetQua.w = float.Parse(quaStr[3]);
|
|
|
+ hasBowTargBtQua = true;
|
|
|
+ ArmBow.ins.phase = int.Parse(quaStr[4]);
|
|
|
+ GameAssistUI.ins.playerScaleAimValue_OnlinePK = int.Parse(quaStr[5]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (key == "arrow") {
|
|
|
+ List<ArrowSync.SyncData> arrowSyncDataList = JsonConvert.DeserializeObject<List<ArrowSync.SyncData>>(data);
|
|
|
+ foreach (var item in arrowSyncMap) {
|
|
|
+ item.Value.hasSetSyncData = false;
|
|
|
+ }
|
|
|
+ GameObject arrowPrefab = ArmBow.ins.arrow;
|
|
|
+ foreach (var item in arrowSyncDataList) {
|
|
|
+ ArrowSync arrowSync;
|
|
|
+ arrowSyncMap.TryGetValue(item.id, out arrowSync);
|
|
|
+ if (arrowSync == null) {
|
|
|
+ GameObject arrowObj = GameObject.Instantiate(arrowPrefab);
|
|
|
+ arrowSync = arrowObj.AddComponent<ArrowSync>();
|
|
|
+ arrowSync.SetSyncData(item, true);
|
|
|
+ arrowSyncMap[item.id] = arrowSync;
|
|
|
+ } else {
|
|
|
+ arrowSync.SetSyncData(item);
|
|
|
+ }
|
|
|
+ arrowSync.hasSetSyncData = true;
|
|
|
+ }
|
|
|
+ List<int> removeIDs = null;
|
|
|
+ foreach (var item in arrowSyncMap) {
|
|
|
+ if (!item.Value.hasSetSyncData) {
|
|
|
+ if (removeIDs == null) removeIDs = new List<int>();
|
|
|
+ removeIDs.Add(item.Key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (removeIDs != null) {
|
|
|
+ foreach (var id in removeIDs) {
|
|
|
+ ArrowSync arrowSync = arrowSyncMap[id];
|
|
|
+ arrowSyncMap.Remove(id);
|
|
|
+ if (arrowSync && arrowSync.gameObject) {
|
|
|
+ GameObject.Destroy(arrowSync.gameObject);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (key == "onBowShoot") {
|
|
|
+ GameEventCenter.ins.onBowArrowShootOut?.Invoke(null, null);
|
|
|
+ }
|
|
|
+ if (key == "DoNextShoot") {
|
|
|
+ gameMode.DoNextShoot();
|
|
|
+ }
|
|
|
+ if (key == "animals") {
|
|
|
+ List<YejiSyncData> syncDataList = JsonConvert.DeserializeObject<List<YejiSyncData>>(data);
|
|
|
+ foreach (var item in animalSyncMap) {
|
|
|
+ item.Value.onlineHandler.isInvalid = true;
|
|
|
+ }
|
|
|
+ foreach (var item in syncDataList) {
|
|
|
+ Yeji animalSync;
|
|
|
+ animalSyncMap.TryGetValue(item.id, out animalSync);
|
|
|
+ if (animalSync == null) {
|
|
|
+ GameObject animalObject = GameObject.Instantiate(gameMode.animalPrefab, Vector3.zero, Quaternion.identity, gameMode.animalsBaseT);
|
|
|
+ animalSync = animalObject.GetComponent<Yeji>();
|
|
|
+ animalSync.onlineHandler.isMirror = true;
|
|
|
+ animalSync.onlineHandler.inputSyncData = item;
|
|
|
+ animalObject.SetActive(true);
|
|
|
+ animalSyncMap[item.id] = animalSync;
|
|
|
+ } else {
|
|
|
+ animalSync.onlineHandler.inputSyncData = item;
|
|
|
+ }
|
|
|
+ animalSync.onlineHandler.isInvalid = false;
|
|
|
+ }
|
|
|
+ List<int> removeIDs = null;
|
|
|
+ foreach (var item in animalSyncMap) {
|
|
|
+ if (item.Value.onlineHandler.isInvalid) {
|
|
|
+ if (removeIDs == null) removeIDs = new List<int>();
|
|
|
+ removeIDs.Add(item.Key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (removeIDs != null) {
|
|
|
+ foreach (var id in removeIDs) {
|
|
|
+ Yeji animalSync = animalSyncMap[id];
|
|
|
+ animalSyncMap.Remove(id);
|
|
|
+ if (animalSync && animalSync.gameObject) {
|
|
|
+ GameObject.Destroy(animalSync.gameObject);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (key == "RUpdate") {
|
|
|
+ if (int.Parse(data) == roundID) {
|
|
|
+ gameMode.OnUpdate(0.033f);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (key == "OnHit") {
|
|
|
+ string[] dataSplits = data.Split(',');
|
|
|
+ int uid = int.Parse(dataSplits[0]);
|
|
|
+ string partName = dataSplits[1];
|
|
|
+ foreach (var item in Yeji.yejiSet) {
|
|
|
+ if (item.onlineHandler.uid == uid) {
|
|
|
+ item.OnHitLogic(null, partName);
|
|
|
+ break; //一定要break,原因1:这是唯一ID,后续也没必要检测了,原因2:这里可能会触发死亡,死亡会触发下个动物生成,Set集合的元素+1,继续遍历会出现modifyException
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void AutoSwitchBanUserControlBow() {
|
|
|
+ BowCamera.ins.banLogic = ArmBow.ins.banLogic = !IsMyPlayerRunning();
|
|
|
+ }
|
|
|
+
|
|
|
+ int lastRoundID = -1;
|
|
|
+ public void OnFrameUpdate() {
|
|
|
+ if (!IsMyPlayerInited()) return;
|
|
|
+ AutoSwitchBanUserControlBow();
|
|
|
+ Upload();
|
|
|
+ if (!IsMyPlayerRunning() && hasBowTargBtQua) {
|
|
|
+ BowCamera.ins.transform.rotation = Quaternion.Lerp(BowCamera.ins.transform.rotation, bowTargetQua, Time.deltaTime * 12);
|
|
|
+ }
|
|
|
+ if (roundID > lastRoundID) {
|
|
|
+ lastRoundID = roundID;
|
|
|
+ gameMode.AddReadyView();
|
|
|
+ }
|
|
|
+ if (gameEnd && !gameMode.gameMgr.gameOver) {
|
|
|
+ gameMode.AnnounceGameOver();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ float lastUploadTime = 0;
|
|
|
+ void Upload() {
|
|
|
+ float curTime = Time.realtimeSinceStartup;
|
|
|
+ if (curTime - lastUploadTime > 0.033) {
|
|
|
+ lastUploadTime = curTime;
|
|
|
+ UploadLogic();
|
|
|
+ UploadBow();
|
|
|
+ UploadArrows();
|
|
|
+ UploadAnimals();
|
|
|
+ UploadRequestUpdate();
|
|
|
+ UploadOnHit();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ void UploadLogic() {
|
|
|
+ if (!IsMainHost()) return;
|
|
|
+ SyncLogicData data = new SyncLogicData().Input(this.gameMode);
|
|
|
+ socketPlayer.UploadPKGameData("logic", data);
|
|
|
+ }
|
|
|
+ void UploadBow() {
|
|
|
+ if (!IsMyPlayerRunning()) return;
|
|
|
+ Quaternion qua = BowCamera.ins.transform.rotation;
|
|
|
+ int aimScaleValue = GameAssistUI.ins.aimScaleValue;
|
|
|
+ if (!GameAssistUI.ins.scaleAimOn) aimScaleValue = 0;
|
|
|
+ socketPlayer.UploadPKGameData("bow", qua.x + "," + qua.y + "," + qua.z + "," + qua.w + "," + ArmBow.ins.phase + "," + aimScaleValue);
|
|
|
+ }
|
|
|
+ Dictionary<int, ArrowSync> arrowSyncMap = new Dictionary<int, ArrowSync>();
|
|
|
+ void UploadArrows() {
|
|
|
+ List<ArrowSync.SyncData> arrowSyncDataList = new List<ArrowSync.SyncData>();
|
|
|
+ foreach (var item in Arrow.arrowSet) {
|
|
|
+ if (item.outputSyncData == null || !item.outputSyncData.inited) continue;
|
|
|
+ arrowSyncDataList.Add(item.outputSyncData);
|
|
|
+ }
|
|
|
+ socketPlayer.UploadPKGameData("arrow", arrowSyncDataList);
|
|
|
+ }
|
|
|
+ Dictionary<int, Yeji> animalSyncMap = new Dictionary<int, Yeji>();
|
|
|
+ void UploadAnimals() {
|
|
|
+ if (!IsMainHost()) return;
|
|
|
+ List<YejiSyncData> syncDataList = new List<YejiSyncData>();
|
|
|
+ foreach (var item in Yeji.yejiSet) {
|
|
|
+ if (item.onlineHandler.outputSyncData == null) continue;
|
|
|
+ syncDataList.Add(item.onlineHandler.outputSyncData);
|
|
|
+ }
|
|
|
+ socketPlayer.UploadPKGameData("animals", syncDataList);
|
|
|
+ }
|
|
|
+ void UploadRequestUpdate() {
|
|
|
+ if (!IsCopyHost()) return;
|
|
|
+ if (!IsMyPlayerRunning()) return;
|
|
|
+ if (gameMode.pauseTimeCounting) return;
|
|
|
+ socketPlayer.UploadPKGameData("RUpdate", this.roundID.ToString());
|
|
|
+ }
|
|
|
+
|
|
|
+ void UploadOnHit() {
|
|
|
+ foreach (var item in Yeji.yejiSet) {
|
|
|
+ if (item.onlineHandler.onHitData != null) {
|
|
|
+ socketPlayer.UploadPKGameData("OnHit", item.onlineHandler.onHitData);
|
|
|
+ item.onlineHandler.onHitData = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|