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();
                }
            });
        }
Beispiel #2
0
 public override int GetHashCode()
 {
     // So that regardless of the unit, only one can be present.
     return(DimensionId.GetHashCode());
 }