/// <summary> ///Unico ponto para enviar mensagens assincronas para a lista de mensagens a enviar ///Desdobra mensagens que estejam indicadas como broadcast /// </summary> /// <param name="mensagem">Mensagem a meter na lista para enviar</param> public static void MeteMensagemParaEnviar(Mensagem mensagem) { ArrayList servidoresVivos = ServerMain.ServidoresVivos; //E a mensagem for para enviar em broadcast if (mensagem._idDestinatarioMensagem.Equals(Mensagem.IPBROADCAST)) { //preciso de multiplicar mensagem para enviar pa todos os servidores Configuration.Debug(Configuration.DEBUG_VOU_REALIZAR_BROADCAST, Configuration.PRI_MIN); foreach (Servidor servidor in servidoresVivos) { Mensagem clone = mensagem.DuplicaMsg(); clone._idDestinatarioMensagem = servidor.Identificacao; lock (_outbox) { _outbox.Add(clone); } } } //Se nao for uma mensagem em broadcast else { lock (_outbox) { _outbox.Add(mensagem); } } }
/// <summary> /// Fila de mensagem de entrada, e por aqui que devem receber as mensagem para o servidor /// </summary> /// <param name="tipoMsg"> define o tipo de mensagem k se pretende receber /// </param> /// <param name="obj"> varia conforme o tipo de mensagem /// "criaJogo" - {nomeMapa, nomeConfig} /// </param> /// <returns> varia conforme a mensagem /// "criaJogo" - {idJogo} /// </returns> public void MessageQueue(Mensagem mensagem) { //Se for uma mensagem vinda de um cliente if (mensagem.TipoMensagemCliente() == true) { try { DoLockGeral(); #region Mensagens vindas do cliente MensagemCliente msgArranjada = (MensagemCliente)mensagem; //Se for uma tentativa de abrir tesouro if (mensagem.TipoIgual(Mensagem.ABRETESOURO)) { TrataAberturaTesouro(msgArranjada.Nick, msgArranjada.Sala, msgArranjada.IdJogo); return; } //se for um movimento if (mensagem.TipoIgual(Mensagem.MOVIMENTO)) { MensagemCliente mensagemRetorno = ServicosEntrada.MovimentoJogador(msgArranjada.Nick, msgArranjada.Sala, msgArranjada.IdJogo); MeteMensagemParaEnviar(mensagemRetorno); return; } #endregion } finally { DoUnlockGeral(); } } //Se for uma mensagem vinda de um servidor if (mensagem.TipoMensagemServidor() == true) { #region Mensagens vindas de um servidor Configuration.Debug("Recebi uma mensagem do servidor " + mensagem._idOriginadorMensagem, Configuration.PRI_MIN); //Vamos ver se esse servidor nao devia estar morto if (Servidor.ServidorEstaVivo(mensagem._idOriginadorMensagem, ServerMain.TodosServidores) == false) { Configuration.Debug("Recebi uma mensagem de um servidor ja declarado como morto", Configuration.PRI_MAX); MensagemServidor msg = MensagemServidor.MensagemAvisoFosteDeclaradoMorto(ServerMain._minhaIdentificacao, mensagem._idOriginadorMensagem); MeteMensagemParaEnviar(msg); return; } MensagemServidor msgArranjada = (MensagemServidor)mensagem; string idJogo = msgArranjada.IdJogo; string idCliente = msgArranjada.IdCliente; int pontuacaoAntiga = msgArranjada.PontuacaoAntiga; int pontuacaoNova = msgArranjada.PontuacaoNova; bool jogoTerminou = msgArranjada.JogoTerminou; //Se for uma mensagem de retorno if (msgArranjada.EMsgDeRetorno() == true) { string guid = msgArranjada.guidUnico; //Vou ver se é retorno para mim lock (_lstRespostasMensagensPendentes) { if (MensagemServidor.ListaContemMensagem(guid, _lstRespostasMensagensPendentes) == true) { Configuration.Debug("Recebi o retorno de uma msg que enviei.", Configuration.PRI_MIN); MensagemServidor.RemoveMensagemPorGuid(guid, _lstRespostasMensagensPendentes); } } } if (mensagem.TipoIgual(Mensagem.UPDATEESTADOGLOBAL)) { Configuration.Debug("Vou realizar um update do meu estado ", Configuration.PRI_MED); RoomDesc novaSala = msgArranjada.NovaSala; string resultadoAccaoCliente = msgArranjada.ResultadoAccaoCliente; ServicosEntrada.RealizaUpdateDoEstado(idJogo, novaSala, idCliente, pontuacaoAntiga, pontuacaoNova, jogoTerminou, resultadoAccaoCliente); RelogioVectorial.IncrementaServidor(mensagem._idOriginadorMensagem, ServerMain._lstRelogiosVectoriais); return; } if (mensagem.TipoIgual(Mensagem.TENTATIVAABRIRTESOURO)) { try { DoLockGeral(); Configuration.Debug("Outro Servidor pediu-me para abrir uma sala de minha responsabilidade", Configuration.PRI_MED); string guidUnico = msgArranjada.guidUnico; ServicosEntrada.RealizaTentativaAbrirSala(idCliente, msgArranjada.NumSala, idJogo, guidUnico); //Incremento o meu relogio vectorial RelogioVectorial.IncrementaServidor(ServerMain._minhaIdentificacao, ServerMain._lstRelogiosVectoriais); return; } finally { DoUnlockGeral(); } } if (mensagem.TipoIgual(Mensagem.ENTRANOVOJOGADORNUMJOGO)) { try { DoLockGeral(); Configuration.Debug("Existe um novo cliente se juntou a um jogo", Configuration.PRI_MED); ServicosEntrada.EntraNovoJogadorNumJogo(msgArranjada.IdJogo, msgArranjada.IdCliente); return; } finally { DoUnlockGeral(); } } if (mensagem.TipoIgual(Mensagem.REGISTANOVOJOGADORNOSISTEMA)) { try { DoLockGeral(); Configuration.Debug("Existe um novo cliente que se registou no sistema", Configuration.PRI_MED); ServicosEntrada.RegistaNovoJogadorNoSistema(msgArranjada.IdCliente); return; } finally { DoUnlockGeral(); } } if (mensagem.TipoIgual(Mensagem.ADICIONANOVOJOGOSISTEMA)) { try { DoLockGeral(); Configuration.Debug("Existe um novo jogo no sistema", Configuration.PRI_MED); ServicosEntrada.InsereNovoJogoSistema(msgArranjada.NovoJogo); return; } finally { DoUnlockGeral(); } } if (mensagem.TipoIgual(Mensagem.AVISOSERVIDORVAISAIR)) { try { DoLockGeral(); Configuration.Debug("Um servidor avisou-me que vai sair do sistema", Configuration.PRI_MED); ServicosEntrada.AvisoServidorVaiSair(msgArranjada._idOriginadorMensagem); RelogioVectorial.IncrementaNivelTodosRelogios(ServerMain._lstRelogiosVectoriais); return; } finally { DoUnlockGeral(); } } if (mensagem.TipoIgual(Mensagem.REMOVESERVIDORSISTEMA)) { try { DoLockGeral(); Configuration.Debug("Vou remover um servidor do meu sistema", Configuration.PRI_MED); ServicosEntrada.RemoveServidorSistema(msgArranjada._idOriginadorMensagem, msgArranjada.NovoEstado); RelogioVectorial.IncrementaNivelTodosRelogios(ServerMain._lstRelogiosVectoriais); return; } finally { DoUnlockGeral(); } } if (mensagem.TipoIgual(Mensagem.MORREU_OUTRO_SERVIDOR)) { Configuration.Debug("Fui informado que o servidor " + msgArranjada.idServidorQueMorreu + " morreu", Configuration.PRI_MED); ServicosEntrada.MorreuOutroServidor(msgArranjada.idServidorQueMorreu, msgArranjada.ListaJogos); RelogioVectorial.IncrementaNivelTodosRelogios(ServerMain._lstRelogiosVectoriais); //Este lock é realizado quando recebo um sinal de STOP e só o "unlocko" quando me vem o novo estado DoUnlockGeral(); return; } if (mensagem.TipoIgual(Mensagem.FOSTE_CONSIDERADO_MORTO)) { try { DoLockGeral(); Configuration.Debug("Argh...Os outros servidores consideraram-me morto!", Configuration.PRI_MED); ServicosEntrada.FuiConsideradoMorto(); return; } finally { DoUnlockGeral(); } } if (mensagem.TipoIgual(Mensagem.STOP)) { //Quando recebo esta mensagem faço stop ao meu sistema e só desligo quando receber o novo estado DoLockGeral(); Configuration.Debug("Recebi uma mensagem de STOP do: " + mensagem._idOriginadorMensagem, Configuration.PRI_MED); ServicosEntrada.TrataStop(mensagem._idOriginadorMensagem, msgArranjada.idServidorQueMorreu, msgArranjada.IdCliente, msgArranjada.IdJogo, msgArranjada.NumSala); return; } if (mensagem.TipoIgual(Mensagem.REPLY_STOP)) { Configuration.Debug("Recebi uma mensagem de REPLY-STOP do: " + mensagem._idOriginadorMensagem, Configuration.PRI_MED); bool pronto = ServicosEntrada.TrataReplyStop(mensagem._idOriginadorMensagem, msgArranjada.idServidorQueMorreu); if (pronto) { //Este unlockGeral recebe o IdCLiente que vai servir de flag para depois fazer unlock ComunicacaoServidor.DoUnlockGeral(); //E vou finalmente responder ao cliente RefazPedidoAberturaDoCliente(msgArranjada.IdCliente, msgArranjada.IdJogo, msgArranjada.NumSala); } return; } return; #endregion } Configuration.Debug("ERRO:Recebi uma mensagem que nem 'e de um cliente nem servidor Tipo --> " + mensagem.Tipo, Configuration.PRI_MAX); }