public Guid RegisterOperationHandler <T>(Action <T> handler,
                                                 bool callOnce = false) where T : MessageBase, new()
        {
            var id = Guid.NewGuid();

            var operationCode = GetOperationCode <T>();

            _logger.Debug(
                $"Registering OperationHandler {handler.Method} for operation {operationCode} (callOnce = {callOnce})");

            if (!_handlers.TryGetValue(operationCode, out var eventHandlers))
            {
                eventHandlers = new ConcurrentDictionary <Guid, EventHandler>();
                _handlers.TryAdd(operationCode, eventHandlers);
            }

            if (!_parsers.ContainsKey(operationCode))
            {
                _parsers.TryAdd(operationCode, (data, offset, length) =>
                                _serializer.DeserializeAs <T>(data, offset, length));
            }

            eventHandlers.TryAdd(id, new EventHandler(msgBase => handler((T)msgBase), callOnce));
            _handlerIdToOperationCodes[id] = operationCode;
            return(id);
        }
        public virtual void Start()
        {
            Logger.Info($"Starting");
            //initialize peer collection
            PeerCollection = new PeerCollection <TP>(Logger, Serializer, Config);
            Logger.Debug($"Peer collection initialized as {PeerCollection.GetType()}");
            //initialize packers
//            Serializer.InitializeDefaultSerializers(8, $"Simple{this.GetType()}Buffer");
            Logger.Debug($"Serializer factory initialized as {Serializer.GetType()}");
            //initialize listener
            foreach (var port in Config.ListenPorts)
            {
                var peerListener = new TL();
                peerListener.Initialize(Logger, PeerCollection, Serializer, Config, TaskSchedulerFactory, port, SocketFactory, RequestSender, _protectionManager);
                PeerListeners.Add(peerListener);
                Logger.Info($"PeerListener initialized as {peerListener.GetType()} on port {port}");
            }


            //call child sub logic
            OnStart();

            //start listening and processing messages
            Listen();

            // checking GC influence
            TaskScheduler.ScheduleOnInterval(TrackMetrics, 1000, 1000);
        }
        private void SendJoinInfoToCurrentMatchmakingGroup()
        {
            lock (_queueSync)
            {
                foreach (var player in _matchmakingPlayers)
                {
                    _logger.Debug($"Sending prejoin info to {player.Id}");
                    var joinInfo = new JoinInfo("", 0, Guid.Empty, JoinStatus.OnMatchmaking, GetCurrentPlayersWeight(),
                                                _totalPlayersNeeded);

                    _messageSender.Send(new JoinInfoEvent(joinInfo), player.Peer);
                }
            }
        }
示例#4
0
        public async Task UpdateRoomState(Guid roomId, int roomPlayersCount, RoomState roomState, string matchMakerUrl, int maxMatchMakingWeight)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(matchMakerUrl))
                {
                    _logger.Error($"SendRoomStateUpdate error: matchmaker URL is empty in properties container");
                    return;
                }

                await _requestSender.SendRequest <UpdateRoomStateResponse>(matchMakerUrl,
                                                                           new UpdateRoomStateRequest(roomId, roomPlayersCount, roomState, maxMatchMakingWeight), (r) =>
                {
                    if (!r.Success)
                    {
                        _logger.Error($"Room update error: {r.Message}");
                    }
                    else
                    {
                        _logger.Debug($"Room update to {matchMakerUrl} with players count {roomPlayersCount}, state {roomState} successful");
                    }
                });
            }
            catch (Exception e)
            {
                _logger.Error($"Update room state error: {e}");
            }
        }
        public void Connect(string address, int port)
        {
            //switch Sockets implementation.BEGIN
            //_socket = new HazelSock(_logger);
            _socket = new LiteNetSock(_logger);
            //switch sockets implementation.END

            _socket.OnPacketReceived += (endPoint, dataPacket, release) =>
            {
                _onPackageReceived(dataPacket, release);
                //todo if using hazel then this part should be considered in releaseAction param
//                _socket.ReturnBufferToPool(dataPacket.Buffer);
            };
            _socket.OnDisconnected += OnDisconnected;

            _socket.OnConnected += ep => { OnConnectedToServer?.Invoke(); };

            _ep = GetIPEndPointFromHostName(address, port, false); // new IPEndPoint(IPAddress.Parse(address), port);
            _socket.Connect(_ep);

            _connected = true;
            _isTicking = false;
            //Send(new ConnectedEvent());
            _socketTickTask = _taskScheduler.ScheduleOnInterval(() =>
            {
                lock (_stateSync)
                {
                    if (!_connected)
                    {
                        return;
                    }

                    lock (_isTickingMutex)
                    {
                        if (_isTicking)
                        {
                            return;
                        }
                        _isTicking = true;
                    }

                    try
                    {
                        _socket.Tick();
                    }
                    catch (Exception ex)
                    {
                        _logger.Error($"Socket tick error: {ex}");
                    }
                    finally
                    {
                        lock (_isTickingMutex)
                            _isTicking = false;
                    }
                }
            }, 0, 10);
            _logger?.Debug($"Receive loop started");
        }
        public void UpdateRoomState(Guid roomId, int currentPlayers, RoomState roomState, int currentMaxWeight)
        {
            var room = GetRoom(roomId);

            if (room == null)
            {
                _logger.Error($"UpdateRoomState error: no room with id {roomId}");
                return;
            }

            room.MaxWeightToJoin = currentMaxWeight;
            room.CurrentWeight   = currentPlayers;
            room.UpdateState(roomState);
            _logger.Debug($"Update received: {roomId} State {roomState}");
        }
        public void Remove(IPendingTask task)
        {
            var pt = task as PendingTask;

            if (pt == null)
            {
                return;
            }
            lock (_listLock)
            {
                var pendingTask = _tasks.FirstOrDefault(t => t == pt);
                if (pendingTask == null)
                {
                    return;
                }
                _logger?.Debug($"Removing {pendingTask.GetActionName()}");
                pendingTask.Dispose();
                _tasks.Remove(pt);
            }
        }
示例#8
0
        private void ProcessMessage(byte[] buffer, int offset, int length)
        {
            MessageBase deserialized  = null;
            ushort      operationCode = 0;

            try
            {
                //probably bad kind of using
                var message = new ArraySegment <byte>(buffer, offset, length).ToArray();

                operationCode = MessageBase.GetOperationCode(message);

                _logger.Debug($"Message received. Operation code: {operationCode}");

                deserialized = _messageDeserializer.DeserializeMessage(operationCode, _serializer, message);
            }
            catch (Exception ex)
            {
                _logger.Error($"ClientOnPackageReceived error: {ex}");
            }

            //calling registered handlers
            lock (_syncCollections)
            {
                if (deserialized != null && operationCode != 0 && _handlers.ContainsKey(operationCode))
                {
                    var callbacksToUnregister = new List <Guid>();
                    foreach (var item in _handlers[operationCode])
                    {
                        try
                        {
                            item.Value.Handler.Invoke(deserialized);
                            if (item.Value.CallOnce)
                            {
                                callbacksToUnregister.Add(item.Key);
                            }
                        }
                        catch (Exception ex)
                        {
                            string targetName = item.Value == null ? "" : item.Value.Handler.Method.ToString();
                            _logger.Error($"ClientOnPackageReceived error: processing message {deserialized.OperationCode} in handler {targetName} {ex}");
                        }
                    }

                    //unregister
                    foreach (var item in callbacksToUnregister)
                    {
                        UnregisterOperationHandler(item);
                    }
                }
                else
                {
                    _logger.Debug($"No handler for message {operationCode}");
                }
            }
        }
示例#9
0
        private void OmMmAuthorizationResponse(AuthorizationResponse response)
        {
            _logger.Debug($"JoinGame: AuthorizationRequest callback fired");
            if (response.ResultCode != ResultCode.OK)
            {
                _logger.Debug($"JoinGame: AuthorizationResponse error: {response.ResultCode}");
                SetAndReportStatus(ShamanClientStatus.AuthorizingMatchMaking, _statusCallback, false,
                                   $"AuthorizationResponse error: {response.ResultCode}");
                return;
            }

            _logger.Debug($"JoinGame: Entering matchmaking");

            //calling next stage
            switch (_joinType)
            {
            case JoinType.RandomJoin:
                _taskScheduler.ScheduleOnceOnNow(EnterMatchMaking);
                break;

            // case JoinType.DirectJoin:
            //     _taskScheduler.ScheduleOnceOnNow(GetRooms);
            //     break;
            // case JoinType.CreateGame:
            //     _taskScheduler.ScheduleOnceOnNow(CreateGame);
            //     break;
            default:
                throw new ArgumentOutOfRangeException();
            }
        }