using BestHTTP.WebSocket; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using MiniJSON; using UnityEngine.SceneManagement; using System.Linq; public class NetHost : MonoBehaviour { public int LocalPlayerID = -1; private int nextLocalItemId = 0; [Serializable] public struct NamedItem { public string Type; public Item Item; } public HashSet<int> Players = new HashSet<int>(); // Start is called before the first frame update void Start() { DontDestroyOnLoad(this); Connect(); } public NamedItem[] ItemsByType; private WebSocket socket; public void Connect() { Clear(); socket = new WebSocket(new System.Uri("wss://blackout.mhack.io/websocket")); socket.PingFrequency = 15000; socket.StartPingThread = true; socket.OnOpen += Opened; socket.OnClosed += Closed; socket.OnMessage += Message; socket.OnError += Error; socket.Open(); } private void Error(WebSocket webSocket, string reason) { Debug.Log("NET: ERROR: " + reason); } private void Closed(WebSocket webSocket, ushort code, string message) { Debug.Log("NET: CLOSED: " + message); Clear(); } private void Message(WebSocket webSocket, string message) { Debug.Log("NET: MESSAGE: " + message); Dictionary<string, object> json = Json.Deserialize(message) as Dictionary<string, object>; if (json != null && json.ContainsKey("type")) { switch ((string)json["type"]) { case "connected": LocalPlayerID = Convert.ToInt32(json["player_id"]); Debug.Log("NET: local player: " + LocalPlayerID); break; case "enter_room": { DestroyRoom(); string map = (string)json["map"]; if (SceneManager.GetActiveScene().name != map) { SceneManager.LoadScene(map); } List<Dictionary<string, object>> items = json.List("items"); foreach (Dictionary<string, object> item in items) { UpdateItem(item); } Item player = SpawnItemLocal("player"); player.transform.position = new Vector3(UnityEngine.Random.Range(-4f, 4f), 1, UnityEngine.Random.Range(-4f, 4f)); break; } case "update_items": { List<Dictionary<string, object>> items = json.List("items"); foreach (Dictionary<string, object> item in items) { UpdateItem(item); } break; } } } } private List<Item> updatesThisFrame = new List<Item>(); public void SendItemUpdate(Item item) { if (item.IsLocal) { updatesThisFrame.Add(item); } } void LateUpdate() { if (updatesThisFrame.Count > 0) { Dictionary<string, object> message = new Dictionary<string, object>(); message.Add("type", "update_items"); message.Add("items", updatesThisFrame.Select(i => i.GetItemData()).ToList()); socket.Send(Json.Serialize(message)); updatesThisFrame.Clear(); } } private void DestroyRoom() { foreach (Item item in items.Values) { Destroy(item.gameObject); } items.Clear(); } private Dictionary<string, Item> items = new Dictionary<string, Item>(); public Item GetItemByType(string type) { return ItemsByType.FirstOrDefault(n => n.Type == type).Item; } private Item SpawnItemLocal(string type) { Item prefab = GetItemByType(type); if (prefab == null) return null; Item item = Instantiate<Item>(prefab); item.Type = type; item.PlayerID = LocalPlayerID; item.ItemID = nextLocalItemId++; item.gameObject.SendMessage("StartLocal", null, SendMessageOptions.DontRequireReceiver); SendItemUpdate(item); items[item.Key] = item; return item; } private void UpdateItem(Dictionary<string, object> itemData) { string key = (string)itemData["key"]; bool shouldDelete = itemData.ContainsKey("__delete__"); if (items.ContainsKey(key)) { if (shouldDelete) { Destroy(items[key].RootTransform.gameObject); items.Remove(key); } else { items[key].UpdateFromData(itemData); } } else if (!shouldDelete) { int playerId = itemData.Key("player_id", Convert.ToInt32); int itemId = itemData.Key("item_id", Convert.ToInt32); string type = (string)itemData["type"]; Item itemPrefab = GetItemByType(type); if (itemPrefab != null) { Item item = Instantiate<Item>(itemPrefab); item.Type = type; item.PlayerID = playerId; item.ItemID = itemId; item.gameObject.SendMessage("StartRemote", null, SendMessageOptions.DontRequireReceiver); item.UpdateFromData(itemData); items[item.Key] = item; } else { Debug.LogError("Can't find Item type " + type); } } } private void Opened(WebSocket webSocket) { Debug.Log("NET: OPENED"); } private void Clear() { if (socket != null) { socket.OnOpen -= Opened; socket.OnClosed -= Closed; socket.OnMessage -= Message; socket.OnError -= Error; } socket = null; } // Update is called once per frame void Update() { } }