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; private static Vector2 RightTop; private static Camera Camera; private static bool Inited; 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; public static string MaxRobotAmtFml; private long RobotConfigID; private string Nickname; private Vector3 Position; private DateTime JoinedTime; private PlayerDirection Direction; private User User; private SmartFox SmartFox; private List DressdataIDs = new List(); private List DressdataNames = new List(); #endregion public static void Init() { if (Inited) { Inited = true; return; } LeftDownBorder = ResourceManager.Get(PlazaRoomLabel.PlayerLeftDownBorder).position; RightTop = ResourceManager.Get(PlazaRoomLabel.PlayerRightTopBorder).position; Camera = ResourceManager.Get(ResourceLabel.MainCamera); XmlDocument document = ConfigManager.GetXmlDocument(ResourceLabel.RobotConfig); XmlNode dataNode = document.SelectSingleNode(ConfigLabel.RootNode).SelectSingleNode(ConfigLabel.ChildNode); XmlAttributeCollection attributes = dataNode.Attributes; int index = 1; MaxRobotAmtFml = attributes[index++].Value; DigitChestRate = float.Parse(attributes[index++].Value); ColorChestRate = float.Parse(attributes[index++].Value); List ints = Auxiliary.StringToInts(',', attributes[index++].Value, null); MinMoveTime = ints[0]; MaxMoveTime = ints[1]; CreateChestRate = float.Parse(attributes[index++].Value); ints = Auxiliary.StringToInts(',', attributes[index++].Value, null); MinChestValue = ints[0]; MaxChestValue = ints[1]; ints = Auxiliary.StringToInts(',', 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(long robotConfigID, bool randomPos, string nickname, List dressdatas) { //if (randomPos) //{ // Vector3? pos; // while ((pos = Raycast()) == null); // Position = pos.Value; // Direction = (PlayerDirection) Random.Range(0, 2); //} //else //{ // Position = SFSPlazaRoomManager.GetDefaultPosition(); // Direction = SFSPlazaRoomManager.DefaultDirection; //} Position = PlazaRoomController.GetDefaultPosition(); Direction = PlazaRoomController.DefaultDirection; try { RobotConfigID = robotConfigID; Nickname = nickname; DressdataNames = dressdatas; DressdataIDs = ConfigManager.GetDressDataIDs(DressdataNames); } catch (Exception e) { foreach (var DressdataName in DressdataNames) { Debug.LogWarning(DressdataName); } Debug.LogWarning(e); } } public void Connect(int sfsRoomID, int maxRobotAmt) { //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 => { MarkAsRobot(evt, sfsRoomID, maxRobotAmt); }); 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 = Loggor.GetRandomUsername(); SmartFox.Send(new LoginRequest(userName, "")); } private void MarkAsRobot(BaseEvent evt, int sfsRoomID, int maxRobotAmt) { //Debug.LogWarning("Robot mark"); User = (User) evt.Params[SFSLabel.DefaultUser]; SFSObject arg = new SFSObject(); arg.PutInt(SFSLabel.CommandID, PlazaRoomReq.MarkAsRobot.GetHashCode()); arg.PutInt(SFSLabel.Data, maxRobotAmt); arg.PutInt(SFSLabel.RoomID, sfsRoomID); arg.PutLong(SFSLabel.UserID, RobotConfigID); SendRequest(arg); } private void SendRequest(SFSObject arg) { arg = GardenSmartFox.WrapIntoArray(new List {arg}); SmartFox.Send(new ExtensionRequest(HandlerID.PlazaRoom.GetHashString(), arg)); } private void SendChestAwardRequest(long chestID) { SFSObject arg = PlazaRoomEvent.WrapChestAwardArg(chestID); SendRequest(arg); } private void SendInstantiateRequest(int receiver) { SFSManager.GardenSmartFox.EventManager.PlazaRoomEvent.SendInstantiateRequset(User.Id, DressdataIDs.ToArray(), RobotConfigID.ToString(), JoinedTime, Position, Direction, Nickname, receiver); } private void OnConnectReturn(BaseEvent evt) { if ((bool) evt.Params[SFSLabel.DefaultResult]) { //Debug.LogWarning("Robot connect succeed"); Login(); } else { //Debug.LogWarning("Robot connect failed"); Deactivate(false); } } private void OnExtensionResponse(BaseEvent evt) { string cmd = evt.Params[SFSLabel.DefaultCommand].ToString(); if (cmd == PlazaRoomRep.JoinRoomSucceed.GetHashString()) { Activate(evt); } else if (cmd == PlazaRoomRep.MarkRobotError.GetHashString()) { Deactivate(false); } else if (cmd == PlazaRoomRep.OtherEnterRoom.GetHashString()) { OnOtherEnterRoom(evt); } } private void OnOtherEnterRoom(BaseEvent evt) { ISFSObject arg = (ISFSObject) evt.Params[SFSLabel.DefaultParams]; int userID = arg.GetInt(SFSLabel.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) { //Debug.LogWarning("Robot Activate"); Activated = true; MoveTime = Random.Range(MinMoveTime, MaxMoveTime); LifetimeTime = Random.Range(MinLifetime, MaxLifetime); CreateChestTime = Random.Range(0, LifetimeTime); JoinedTime = DateUtil.GetTimeFromSeconds(((ISFSObject) evt.Params[SFSLabel.DefaultParams]).GetLong(SFSLabel.DateTime).ToString()); //Debug.Log(JoinedTime); SendInstantiateRequest(-1); } private bool Behaviour() { if (!Activated) { return false; } if (!SFSManager.GardenSmartFox.PlazaRoomController.JoinedPlazaRoom) { 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"); Vector3? pos = Raycast(); if (pos != null) { Position = pos.Value; SFSManager.GardenSmartFox.EventManager.PlazaRoomEvent.SendSynchronizeDestination(User.Id, Position); } } } private Vector3? Raycast() { 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)) { if (hitInfo.collider.tag == Tags.PlazaChestTag) { //Debug.LogWarning("射线被箱子阻挡"); return null; } else { Vector3 destination = PlazaRoom.HitPositionToDestination(hitInfo.point); return destination; } } else { //Debug.LogWarning("射线检测失败"); return null; } } 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() { 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.PlazaRoomController.CurrentRoomData; int round = Random.Range(1, roomData.MaxPlayer + 1); int value = Random.Range(MinChestValue, MaxChestValue); Vector3 playerPos = SFSManager.GardenSmartFox.PlazaRoomController.UserInstanceDictionary[User.Id].Player.transform.position; Vector3 chestPos = ChestManager.PlayerPosToChestPos(playerPos); ChestType type = (ChestType) Random.Range(1, 4); SFSManager.GardenSmartFox.EventManager.PlazaRoomEvent.CreateChest(round, value, type, roomData.ID, -2, chestPos); } } private float GetChestTime = 3; private float GetChestTimer; private float MaxChestDistance = 8; private List OperatedChestIDs = new List(); private void GetChestAwardBehaviour() { 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]); } } } private List DetectChest() { List chests = new List(); for (int i = 0; i < ChestManager.PlazaRoomChests.Count; i++) { if (Mathf.Abs(ChestManager.PlazaRoomChests[i].transform.position.x - Position.x) <= MaxChestDistance) { if (OperatedChestIDs.Contains(ChestManager.PlazaRoomChests[i].ChestData.ID)) { //Debug.LogWarning("this chest has been operated"); } else { chests.Add(ChestManager.PlazaRoomChests[i]); } } else { //Debug.LogWarning("this chest is too far"); //Debug.LogWarning(Mathf.Abs(ChestMge.PlazaRoomChests[i].transform.position.x - Position.x)); } } 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 if (chest.ChestData.ChestType == ChestType.System) { if (chest.IsActive) { get = true; } else { get = false; } } else { get = true; } OperatedChestIDs.Add(chest.ChestData.ID); if (get) { SendChestAwardRequest(chest.ChestData.ID); //Debug.LogWarning("get a chest"); } 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 " + delay); Activated = false; if (delay) { DelayCall.Call(Random.Range(MinDelayTime, MaxDelayTime), Remove); } else { Remove(); } } private void Remove() { RobotManager.Robots.Remove(this); SmartFox.Disconnect(); } }