private void PlaceHandler(SBRemoteClient source, int x, int y, int l, bool vertical) { lock (_syncRoot) { Player p = _a.Client == source ? _a : _b; if (this.State == GameState.Init) { if (p.LeftSpace >= l && l <= 4 && l >= 1) { p.LeftSpace -= l; if (vertical) { for (int cy = y; cy < y + l; cy++) { p.Field[x, cy] = CellState.Alive; } } else { for (int cx = x; cx < x + l; cx++) { p.Field[cx, y] = CellState.Alive; } } } if (_a.LeftSpace <= 0 && _b.LeftSpace <= 0) { this.SetState(GameState.TurnA); } } } }
/// <summary> /// Потеря соединения /// </summary> /// <param name="c"></param> private void ConnectionLostHandler(SBRemoteClient c) { if (c.Name != null) { this.SendToAll(new MsgChatMessage() { Text = c.Name + " соединение потеряно" }); if (c.State != KnownClientState.InGame) { this.SendToAll(new MsgRemoveKnownClient() { Id = c.Id }); using (_knownClients.Write()) { _knownClients.Object.Remove(c.Id); } } } else { using (_unnamedClients.Write()) { _unnamedClients.Object.Remove(c); } } }
/// <summary> /// Процедура, выполняющаяся при выходе из игры одного из игроков /// </summary> /// <param name="source"></param> private void LeaveHandler(SBRemoteClient source) { lock (_syncRoot) { if (this.State != GameState.Idle) { Player p = _a.Client == source ? _a : _b; Player o = _a.Client == source ? _b : _a; if (o.Client.State == KnownClientState.InGame) { o.Client.Send(new MsgChatMessage() { Text = "Ваш противник покинул игру!" }); } source.SetState(KnownClientState.Free); if (_a.Client.State != KnownClientState.InGame && _b.Client.State != KnownClientState.InGame) { this.SetState(GameState.Idle); } } } }
private void StateChangedHandler(SBRemoteClient source, KnownClientState st) { this.SendToAll(new MsgKnownClientStateUpdate() { Id = source.Id, State = st }); }
private void Subscribe(SBRemoteClient c) { c.OnChatMessage += msg => ChatMessageHandler(c, msg); c.OnFire += (x, y) => FireHandler(c, x, y); c.OnPlace += (x, y, l, v) => PlaceHandler(c, x, y, l, v); c.OnLeaveGame += () => LeaveHandler(c); c.OnConnectionLost += () => ConnectionLostHandler(c); }
/// <summary> /// Сообщения в чат /// </summary> /// <param name="source"></param> /// <param name="msg"></param> private void ChatMessageHandler(SBRemoteClient source, string msg) { if (source.State != KnownClientState.InGame) { this.SendToAll(new MsgChatMessage() { Text = source.Name + " - " + msg }); } }
/// <summary> /// Сообщения в чат /// </summary> /// <param name="source"></param> /// <param name="msg"></param> private void ChatMessageHandler(SBRemoteClient source, string msg) { lock (_syncRoot) { if (source.State == KnownClientState.InGame && this.State != GameState.Idle) { var pckt = new MsgChatMessage() { Text = source.Name + " - " + msg }; _a.Client.Send(pckt); _b.Client.Send(pckt); } } }
/// <summary> /// Начало игры /// </summary> /// <param name="c"></param> /// <param name="opponentId"></param> /// <param name="password"></param> private void BeginGameHandler(SBRemoteClient c, Guid opponentId, string password) { SBRemoteClient opponent; if (c.State == KnownClientState.Free || c.State == KnownClientState.Ready) { using (_knownClients.Read()) { if (!_knownClients.Object.TryGetValue(opponentId, out opponent)) { opponent = null; } } if (opponent != null) { if (opponent.Password == password) { c.SetState(KnownClientState.InGame); opponent.SetState(KnownClientState.InGame); var g = new SBGame(c, opponent); g.OnScoreChanged += gc => GameScoreChangedHalder(gc); g.OnGameFinished += () => GameFinishedHandler(g); using (_games.Write()) { _games.Object.Add(g.Id, g); } this.SendToAll(new MsgNewGame() { Id = g.Id, PlayerA = g.PlayerA, PlayerB = g.PlayerB }); } else { c.Send(new MsgChatMessage() { Text = "Неверный пароль!" }); } } } }
/// <summary> /// Конструктор класса игры. В качестве входных параметров идут классы с информацией об удаленном клиенте игроков. /// </summary> /// <param name="a"></param> /// <param name="b"></param> public SBGame(SBRemoteClient a, SBRemoteClient b) { _a = new Player() { Client = a, TurnState = GameState.TurnA }; _b = new Player() { Client = b, TurnState = GameState.TurnB }; this.Subscribe(a); this.Subscribe(b); this.Id = Guid.NewGuid(); this.State = GameState.Init; }
/// <summary> /// Процедура, выполняющаяся при потере соединения /// </summary> /// <param name="source"></param> private void ConnectionLostHandler(SBRemoteClient source) { lock (_syncRoot) { if (this.State != GameState.Idle) { Player p = _a.Client == source ? _a : _b; Player o = _a.Client == source ? _b : _a; if (o.Client.State == KnownClientState.InGame) { o.Client.Send(new MsgChatMessage() { Text = "У вашего противника проблемы с соединением. Ждите..." }); } } } }
/// <summary> /// Создание нового соединения /// </summary> /// <param name="cnn"></param> private void NewConnectionHandler(Connection cnn) { var c = new SBRemoteClient(cnn); c.OnRegisterName += name => RegisterNameHandler(c); c.OnRestoreSession += id => RestoreSessionHandler(id, cnn); c.OnChatMessage += msg => ChatMessageHandler(c, msg); c.OnStateChanged += st => StateChangedHandler(c, st); c.OnBeginGame += (opponentId, pwd) => BeginGameHandler(c, opponentId, pwd); c.OnConnectionLost += () => ConnectionLostHandler(c); c.Start(); using (_unnamedClients.Write()) { _unnamedClients.Object.AddLast(c); } OnNewConnection(c, cnn); }
/// <summary> /// Процедура, вызывающаяся во время сражения /// </summary> /// <param name="source"></param> /// <param name="x"></param> /// <param name="y"></param> private void FireHandler(SBRemoteClient source, int x, int y) { lock (_syncRoot) { Player p = _a.Client == source ? _a : _b; Player o = _a.Client == source ? _b : _a; if (this.State == p.TurnState) { switch (o.Field[x, y]) { case CellState.Dead: case CellState.FreeFired: break; case CellState.Free: { o.Field[x, y] = CellState.FreeFired; o.Client.Send(new MsgFire() { X = x, Y = y, Dead = false }); p.Client.Send(new MsgFireResult() { Miss = true, Dead = false }); this.SetState(o.TurnState); } break; case CellState.Alive: { o.Field[x, y] = CellState.Dead; var dead = this.CheckIsDead(o.Field, x, y); o.Client.Send(new MsgFire() { X = x, Y = y, Dead = dead }); p.Client.Send(new MsgFireResult() { Miss = false, Dead = dead }); p.Score++; OnScoreChanged(new MsgUpdateGame() { Id = this.Id, ScoresA = _a.Score, ScoresB = _b.Score }); if (p.Score >= 20) { this.SetState(GameState.Finished); OnGameFinished(); p.Client.Send(new MsgGameFinished() { WinnerName = p.Client.Name }); o.Client.Send(new MsgGameFinished() { WinnerName = p.Client.Name }); } else { this.SetState(p.TurnState); } } break; default: throw new NotImplementedException(""); } } } }
/// <summary> /// Регистрация имени /// </summary> /// <param name="clnt"></param> private void RegisterNameHandler(SBRemoteClient clnt) { using (_unnamedClients.Write()) { _unnamedClients.Object.Remove(clnt); } KnownClientInfo[] clients; using (_knownClients.Read()) { clients = _knownClients.Object.Values.Select( c => new KnownClientInfo() { Id = c.Id, Name = c.Name, State = c.State } ).ToArray(); } clnt.Send(new MsgAddKnownClients() { Clients = clients }); Tuple <MsgNewGame, MsgUpdateGame>[] games; using (_games.Read()) { games = _games.Object.Values.Select( g => Tuple.Create( new MsgNewGame() { Id = g.Id, PlayerA = g.PlayerA, PlayerB = g.PlayerB }, new MsgUpdateGame() { Id = g.Id, ScoresA = g.ScoresA, ScoresB = g.ScoresB } ) ).ToArray(); } Array.ForEach(games, g => { clnt.Send(g.Item1); clnt.Send(g.Item2); }); using (_knownClients.Write()) { _knownClients.Object.Add(clnt.Id, clnt); } SendToAll(new MsgAddKnownClients() { Clients = new[] { new KnownClientInfo() { Id = clnt.Id, Name = clnt.Name, State = clnt.State } } }); }