using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Security.Policy; using System.Xml; using Sfs2X; using Sfs2X.Core; using Sfs2X.Entities; using Sfs2X.Entities.Data; using Sfs2X.Requests; using Sfs2X.Util; using UnityEngine; using Random = UnityEngine.Random; public class Robot { #region Config private static Vector2 LeftDownBorder; //todo private static Vector2 RightTop; //todo private static Camera Camera; //todo private static bool Initialized; private static int MinChestValue; private static int MaxChestValue; private static float MinLifetime; private static float MaxLifetime; private static float CreateChestRate; private static float ColorChestRate; private static float DigitChestRate; private static float MinMoveTime; private static float MaxMoveTime; private static float MinRobotCreateTime; private static float MaxRobotCreateTime; private static string MaxRobotAmtFml; private static string ConfigName = "robot_config"; private static string RootNodeName = "data"; private static string DataNodeName = "item"; private string Nickname; private Vector3 Position; private PlayerDirection Direction; private User User; private SmartFox SmartFox; private List DressdataIDs = new List(); private List DressdataNames = new List(); #endregion public static void Initialize() { if (Initialized) { Initialized = true; return; } LeftDownBorder = ManaReso.Get("PlayerLeftDownBorder").position; RightTop = ManaReso.Get("PlayerRightTopBorder").position; Camera = ManaReso.Get("MainCamera"); XmlDocument document = ManaData.GetXmlDocument(ConfigName); XmlNode dataNode = document.SelectSingleNode(RootNodeName).SelectSingleNode(DataNodeName); XmlAttributeCollection attributes = dataNode.Attributes; int index = 1; List ints = Auxiliary.IntListParse(',', attributes[index++].Value, null); MinRobotCreateTime = ints[0]; MaxRobotCreateTime = ints[1]; MaxRobotAmtFml = attributes[index++].Value; DigitChestRate = float.Parse(attributes[index++].Value); ColorChestRate = float.Parse(attributes[index++].Value); ints = Auxiliary.IntListParse(',', attributes[index++].Value, null); MinMoveTime = ints[0]; MaxMoveTime = ints[1]; CreateChestRate = float.Parse(attributes[index++].Value); ints = Auxiliary.IntListParse(',', attributes[index++].Value, null); MinChestValue = ints[0]; MaxChestValue = ints[1]; ints = Auxiliary.IntListParse(',', attributes[index++].Value, null); MinLifetime = ints[0]; MaxLifetime = ints[1]; //Debug.Log($"RobotConfig {MinRobotCreateTime}"); //Debug.Log($"RobotConfig {MaxRobotCreateTime}"); //Debug.Log($"RobotConfig {MaxRobotAmtFml}"); //Debug.Log($"RobotConfig {DigitChestRate}"); //Debug.Log($"RobotConfig {ColorChestRate}"); //Debug.Log($"RobotConfig {MinMoveTime}"); //Debug.Log($"RobotConfig {MaxMoveTime}"); //Debug.Log($"RobotConfig {CreateChestRate}"); //Debug.Log($"RobotConfig {MinChestValue}"); //Debug.Log($"RobotConfig {MaxChestValue}"); //Debug.Log($"RobotConfig {MinLifetime}"); //Debug.Log($"RobotConfig {MaxLifetime}"); } public Robot(Vector3 position, PlayerDirection direction) { Position = position; Direction = direction; } public void Connect(int sfsRoomID, int maxRobot) { Debug.LogWarning("Robot connect"); SmartFox = new SmartFox(); SmartFox.AddEventListener(SFSEvent.CONNECTION, OnConnectReturn); SmartFox.AddEventListener(SFSEvent.CONNECTION_LOST, (evt) => Deactivate(false)); SmartFox.AddEventListener(SFSEvent.LOGIN, evt => { Mark(evt, sfsRoomID, maxRobot); }); SmartFox.AddEventListener(SFSEvent.LOGIN_ERROR, (evt) => Deactivate(false)); SmartFox.AddEventListener(SFSEvent.LOGOUT, (evt) => Deactivate(false)); SmartFox.AddEventListener(SFSEvent.EXTENSION_RESPONSE, OnExtensionResponse); ConfigData configData = new ConfigData { Host = BaseConnector.Host, Port = BaseConnector.TcpPort, Zone = BaseConnector.Zone, }; SmartFox.Connect(configData); } private void Login() { Debug.LogWarning("Robot login"); string userName = Random.Range(0f, 1000f).ToString(); SmartFox.Send(new LoginRequest(userName, "")); } private void Mark(BaseEvent evt, int sfsRoomID, int maxRobot) { Debug.LogWarning("Robot mark"); User = (User) evt.Params["user"]; SFSObject arg = new SFSObject(); arg.PutInt(Label.CommandID, PlazaRoomReq.MarkAsRobot.GetHashCode()); arg.PutInt(Label.RoomID, sfsRoomID); arg.PutInt(Label.Data, maxRobot); SendRequest(arg); } private void SendRequest(SFSObject arg) { arg = GardenSmartFox.WrapIntoArray(new List {arg}); SmartFox.Send(new ExtensionRequest(HandlerID.PlazaRoom.GetHashString(), arg)); } private void SendInstantiateRequest(int receiver) { SFSManager.GardenSmartFox.EventManager.PlazaRoomEvent.SendInstantiateRequset(User.Id, DressdataIDs.ToArray(), Position, Direction, Nickname, receiver); } private void OnConnectReturn(BaseEvent evt) { if ((bool) evt.Params["success"]) { Debug.LogWarning("Robot connect succeed"); Login(); } else { Debug.LogWarning("Robot connect failed"); Deactivate(false); } } private void OnExtensionResponse(BaseEvent evt) { string cmd = evt.Params["cmd"].ToString(); if (cmd == PlazaRoomRep.JoinRoomSucceed.GetHashString()) { Activate(evt); } else if (cmd == PlazaRoomRep.MarkRobotError.GetHashString()) { Deactivate(false); } else if (cmd == PlazaRoomRep.OtherEnterRoom.GetHashString()) //todo { OnOtherEnterRoom(evt); } } private void OnOtherEnterRoom(BaseEvent evt) { ISFSObject arg = (ISFSObject) evt.Params["params"]; int userID = arg.GetInt(Label.UserID); if (userID != User.Id) { SendInstantiateRequest(userID); } } public bool Update() { if (SmartFox != null) { SmartFox.ProcessEvents(); } return Behaviour(); } private bool Activated; private void Activate(BaseEvent evt) { if (!SFSManager.GardenSmartFox.PlazaRoomManager.InPlazaRoom) { Deactivate(false); } Debug.LogWarning("Robot Activate"); Activated = true; MoveTime = Random.Range(MinMoveTime, MaxMoveTime); LifetimeTime = Random.Range(MinLifetime, MaxLifetime); CreateChestTime = Random.Range(0, LifetimeTime); try { ISFSObject arg = evt.Params["params"] as ISFSObject; Nickname = arg.GetUtfString(Label.Data); DressdataNames = arg.GetUtfStringArray(Label.DataArray).ToList(); DressdataIDs = ManaData.GetDressDataIDs(DressdataNames); SendInstantiateRequest(-1); } catch (Exception e) { Debug.LogWarning(e); Deactivate(false); } } private bool Behaviour() { if (!Activated) { return false; } //if (LifetimeBehaviour()) //{ // return true; //} //MoveBehaviour(); //CreateChestBehaviour(); //GetChestAwardBehaviour(); return false; } private float MoveTime; private float MoveTimer; private void MoveBehaviour() { MoveTimer += Time.deltaTime; if (MoveTimer >= MoveTime) { MoveTimer = 0; Debug.LogWarning("Robot move"); Raycast(); } } private void Raycast() //todo { Vector3 origin = new Vector3(Random.Range(LeftDownBorder.x, RightTop.x), Random.Range(LeftDownBorder.y, RightTop.y), Camera.transform.position.z); Ray ray = new Ray(origin, Vector3.forward); RaycastHit hitInfo; if (Physics.Raycast(ray, out hitInfo)) { Vector3 destination = PlazaRoom.HitPositionToDestination(hitInfo.point); SFSManager.GardenSmartFox.EventManager.PlazaRoomEvent.SendSynchronizeDestination(User.Id, destination); Position = destination; } else { Debug.LogWarning("射线检测失败"); } } private float LifetimeTime; private float LifetimeTimer; private bool LifetimeBehaviour() { LifetimeTimer += Time.deltaTime; if (LifetimeTimer >= LifetimeTime) { Debug.LogWarning("Robot lifetime over"); return true; } else { return false; } } private bool CreateChestLock; private float CreateChestTime; private float CreateChestTimer; private void CreateChestBehaviour() //todo { if (CreateChestLock) { return; } CreateChestTimer += Time.deltaTime; if (CreateChestTimer >= CreateChestTime) { CreateChestLock = true; if (Random.Range(0f, 1f) >= CreateChestRate) { Debug.LogWarning("create chest ran out of luck"); return; } Debug.LogWarning("Robot create a chest"); RoomData roomData = SFSManager.GardenSmartFox.PlazaRoomManager.CurrentRoomData; int round = Random.Range(1, roomData.MaxPlayer + 1); int value = Random.Range(MinChestValue, MaxChestValue); Vector3 position = ChestMge.PlayerPosToChestPos(Position); ChestType type = (ChestType) Random.Range(1, 4); SFSManager.GardenSmartFox.EventManager.PlazaRoomEvent.CreateChest(round, value, type, roomData.ID, -1, position); } } private float GetChestTime = 3; private float GetChestTimer; private float MaxChestDistance = 8; //todo private List OperatedChestIDs = new List(); private void GetChestAwardBehaviour() //todo { GetChestTimer += Time.deltaTime; if (GetChestTimer >= GetChestTime) { GetChestTimer = 0; Debug.LogWarning("Robot try get some chests"); List chests = DetectChest(); Debug.LogWarning($"{chests.Count} chest/chests is available"); for (int i = 0; i < chests.Count; i++) { TryGetChestAward(chests[i]); } } //Debug.LogWarning("robot get a chest"); } private List DetectChest() { List chests = new List(); for (int i = 0; i < ChestMge.PlazaRoomChests.Count; i++) { if (Mathf.Abs(ChestMge.PlazaRoomChests[i].transform.position.x - Position.x) <= MaxChestDistance) { if (OperatedChestIDs.Contains(ChestMge.PlazaRoomChests[i].ChestData.ID)) { Debug.LogWarning("this chest has been operated"); } else { chests.Add(ChestMge.PlazaRoomChests[i]); } } else { Debug.LogWarning("this chest is too far"); } } return chests; } private void TryGetChestAward(PlazaRoomChest chest) { float rate = Random.Range(0f, 1f); bool get = false; if (chest.ChestData.ChestType == ChestType.GuessColor) { if (rate < ColorChestRate) { get = true; } else { get = false; } } else if (chest.ChestData.ChestType == ChestType.GuessNumber) { if (rate < DigitChestRate) { get = true; } else { get = false; } } else { get = true; } OperatedChestIDs.Add(chest.ChestData.ID); if (get) { SFSManager.GardenSmartFox.EventManager.PlazaRoomEvent.GetChestAward(chest.ChestData.ID); } else { Debug.LogWarning("get chest ran out of luck"); } } private static float MinDelayTime = 3f; private static float MaxDelayTime = 10f; public void Deactivate(bool delay) { Debug.LogWarning("Robot disconnect"); Activated = false; if (delay) { DelayCall.Call(Random.Range(MinDelayTime, MaxDelayTime), Remove); } else { Remove(); } } private void Remove() { RobotManager.Robots.Remove(this); SmartFox.Disconnect(); } }