private void StartSendingMessages() { Task.Run(() => { while (server.Clients.Contains(this)) { try { if (UserId.HasValue && FocusedObjectId.HasValue && server.Dimensions[DimensionId].Map.LoadedObjects.ContainsKey(FocusedObjectId.Value)) { GameObject go = server.Dimensions[DimensionId].Map.LoadedObjects[FocusedObjectId.Value]; //Deep Clone to make thread-safe //TODO: Make it more efficient ConcurrentDictionary <Guid, GameObject> objClone; ConcurrentDictionary <Guid, GameEntity> entClone; lock (server.Dimensions[DimensionId].Map.LoadedObjects) objClone = MessagePackSerializer.Deserialize <ConcurrentDictionary <Guid, GameObject> >(MessagePackSerializer.Serialize(server.Dimensions[DimensionId].Map.LoadedObjects)); lock (server.Dimensions[DimensionId].Map.LoadedEntities) entClone = MessagePackSerializer.Deserialize <ConcurrentDictionary <Guid, GameEntity> >(MessagePackSerializer.Serialize(server.Dimensions[DimensionId].Map.LoadedEntities)); ConcurrentDictionary <Guid, GameObject> objCloneToSend = new ConcurrentDictionary <Guid, GameObject>(); ConcurrentDictionary <Guid, GameEntity> entCloneToSend = new ConcurrentDictionary <Guid, GameEntity>(); (long, long)goChunk = Map.PositionToChunkIndex(go.Coordinates); foreach ((Guid id, GameObject o) in objClone) { (long, long)oChunk = Map.PositionToChunkIndex(o.Coordinates); if (Math.Abs(oChunk.Item1 - goChunk.Item1) <= Map.CHUNK_RANGE && Math.Abs(oChunk.Item2 - goChunk.Item2) <= Map.CHUNK_RANGE) { objCloneToSend.TryAdd(id, o); } } foreach ((Guid id, GameEntity e) in entClone) { (long, long)eChunk = Map.PositionToChunkIndex(e.Coordinates); if (Math.Abs(eChunk.Item1 - goChunk.Item1) <= Map.CHUNK_RANGE && Math.Abs(eChunk.Item2 - goChunk.Item2) <= Map.CHUNK_RANGE) { entCloneToSend.TryAdd(id, e); } } lock (go) { while (externalPacks.TryDequeue(out ClientPack result)) { Send(result); } if (objCloneToSend.ContainsKey(FocusedObjectId.Value)) { Queue <ChatMessage> messages = new Queue <ChatMessage>(); while (MessageOutbox.TryDequeue(out ChatMessage m)) { messages.Enqueue(m); } ClientPack pack = new ClientPack() { Chunks = server.Dimensions[DimensionId].Map.GetLocalChunks(objCloneToSend[FocusedObjectId.Value].Coordinates.Item1, objCloneToSend[FocusedObjectId.Value].Coordinates.Item2, DimensionId, Path.Combine(server.saveDirectoryPath, "Dimensions", DimensionId.ToString()), server.Dimensions[DimensionId].DefaultSeedString), GameObjects = objCloneToSend, GameEntities = entCloneToSend, NewChats = messages }; Send(pack); } else { //throw new Exception("Player object removed"); //Player object now CAN be removed when the player is shifting Dimensions. Just don't send them anything this round } } } else { while (externalPacks.TryDequeue(out ClientPack result)) { Send(result); } } } catch (Exception e) { if (e.GetType() == typeof(Exception)) { server.logger(EndPointString + " disconnected: " + e.Message); } server.RemoveClient(this); } Task.Delay(5).Wait(); } }); }
public override int GetHashCode() { // So that regardless of the unit, only one can be present. return(DimensionId.GetHashCode()); }