Anúncio

Como por o "Relog" ...
 
Notifications
Clear all

[Resolvido] Como por o "Relog" para a Seleção de Personagem estilo BPT

3 Posts
2 Usuários
2 Reactions
43 Visualizações
Lou
 Lou
(@lou)
Posts: 25
Mentor Respeitado
Topic starter
 

Vamos lá, vou trazer mais um tutorial nesse tutorial venho trazer um relog estilo bpt, pode conter bugs é mais para estudos vamos no tutorial. 

Fase 1: Preparação - Criando o Comando de Comunicação

Tudo começa com a criação de um novo "comando" (Opcode) para que o cliente e o servidor possam "conversar" sobre a ação de relog.

Passo 1: Definir o Novo Opcode

    1. Localize o Ficheiro de Opcodes: Abra o ficheiro de cabeçalho (NetType.h) onde todos os códigos de operação da rede são definidos. Geralmente, este ficheiro é partilhado entre o servidor e o cliente.

    2. Adicione o Novo Comando: No final da lista de enum de opcodes, antes do OPCODE_END, adicione a nova linha para o nosso comando de relog.

        // --- INÍCIO DA NOSSA ADIÇÃO ---
          OPCODE_CHAR_RELOG_REQUEST, // Comando para solicitar o retorno à seleção de personagem
          // --- FIM DA NOSSA ADIÇÃO ---

       

      Agora, vamos ensinar o servidor a reagir quando receber o novo comando. A tarefa do servidor é crucial: salvar o progresso do jogador com segurança e autorizar o cliente a prosseguir.

      Passo 2: Processar o Pedido de Relog

      1. Localize o Processador de Pacotes: Abra o ficheiro principal do servidor que lida com os pacotes recebidos dos jogadores.

        • Ficheiro:  SrcServer/src/Server/OnSever.cpp

          Encontre a Função Principal: Dentro deste ficheiro, encontre a função que contém um grande switch para tratar os opcodes.

          Função: RecvUserPacket()

        • Adicione o Novo case: Dentro do switch, adicione o bloco de código para tratar o nosso novo opcode.

          Código em OnSever.cpp:

          // Dentro da função RecvUserPacket(int conn, ...), dentro do switch...
          
          // --- INÍCIO DA NOSSA ADIÇÃO ---
          case OpCode::OPCODE_CHAR_RELOG_REQUEST:
              {
                  // Primeiro, obtemos um ponteiro para as informações do jogador que enviou o pedido.
                  rsPLAYINFO* lpPlayInfo = &rsPlayInfo[conn];
          
                  // Verificação de segurança: garantimos que o jogador está válido e no jogo.
                  if (lpPlayInfo->lpsmSock && lpPlayInfo->smCharInfo.State == smCHAR_STATE_USER)
                  {
                      // Passo MAIS IMPORTANTE: Chamamos a função existente para salvar o personagem no DB.
                      // Isto garante que nenhum progresso seja perdido.
                      // Os parâmetros podem variar, mas a ideia é salvar sem desconectar.
                      DBSaveCharacter(lpPlayInfo, TRUE, FALSE);
          
                      // Preparamos um pacote de resposta para enviar de volta ao cliente.
                      smTRANS_COMMAND smTransCommand;
                      smTransCommand.code = OpCode::OPCODE_CHAR_RELOG_REQUEST; // Usamos o mesmo opcode
                      smTransCommand.size = sizeof(smTRANS_COMMAND);
          
                      // Enviamos a confirmação para o cliente, autorizando-o a prosseguir.
                      lpPlayInfo->lpsmSock->Send((char*)&smTransCommand, smTransCommand.size, TRUE);
                  }
              }
              break;
          // --- FIM DA NOSSA ADIÇÃO ---

          Agora o servidor agora sabe o que fazer. Ele recebe o pedido, salva o personagem e dá a "luz verde" para o cliente.

          agora seguimos para a parte no game:

          Fase 3: Implementando a Lógica no Cliente (SrcGame)

           

          Finalmente, vamos fazer as alterações no cliente para que o jogador possa iniciar o processo e para que o cliente saiba como reagir à "luz verde" do servidor.

          Passo 3.1: Adicionar o Botão "Selecionar Personagem" na UI

          1. Contexto: Esta parte depende de como a sua interface de utilizador (UI) foi construída. Você precisará de adicionar um novo botão à janela do menu do jogo (a que tem "Sair", "Opções", etc.).

          2. Ação: Na função que é chamada quando este novo botão é clicado, adicione o código para enviar o nosso opcode para o servidor.

            Código na Função de Clique do Botão:

            void OnClick_Button_GoToCharSelect() 
            {
                // Cria um pacote simples de comando.
                smTRANS_COMMAND smTransCommand;
                smTransCommand.code = OpCode::OPCODE_CHAR_RELOG_REQUEST; // Define o nosso novo comando
                smTransCommand.size = sizeof(smTRANS_COMMAND);
            
                // Envia o pacote para o servidor.
                // g_Socket é o nome provável do socket global de conexão.
                send(g_Socket, (char*)&smTransCommand, smTransCommand.size, 0);
            }

            Passo 3.2: Lidar com a Resposta do Servidor

            Agora, a parte final e mais importante no cliente. Precisamos de dizer ao jogo o que fazer quando o servidor enviar a confirmação.

            1. Localize o Processador de Pacotes do Cliente: Abra o ficheiro do cliente que recebe e trata os pacotes vindos do servidor.

              • Ficheiro: SrcGame/src/netplay.cpp

            2. Encontre a Função e o switch: Assim como no servidor, encontre a função que contém o switch dos opcodes.

            3. Adicione o Novo case:

               Código em netplay.cpp:

              // Dentro do switch que processa os pacotes...
              
              // --- INÍCIO DA NOSSA ADIÇÃO ---
              case OpCode::OPCODE_CHAR_RELOG_REQUEST:
                  {
                      // Esta é a ação chave que muda tudo.
              
                      // 1. Limpamos os recursos do mundo do jogo atual.
                      // Esta função deve remover monstros, NPCs e outros jogadores da memória.
                      ReleaseField(); 
              
                      // 2. Mudamos o estado do jogo.
                      // Em vez de chamar a função para fechar o jogo (como PostQuitMessage),
                      // nós chamamos a função que define o "modo" do jogo.
                      // O nome exato pode variar (ex: GAME_STATE_SELECT_CHAR, GAME_STATE_ID).
                      SetGameState(GAME_STATE_CHAR_SEL);
                  }
                  break;
              // --- FIM DA NOSSA ADIÇÃO ---

              Com isso a função a função vai funcionar, agora é com vocês!

 
Postado : 02/07/2025 5:12 pm
potras18 and Raka reacted
Raka
 Raka
(@rakabr)
Posts: 26
Admin
 

Seja bem-vindo! Ótimo guia e muito bem organizado. 😉 

Apenas criando um legado 😊

 
Postado : 02/07/2025 6:18 pm
Lou
 Lou
(@lou)
Posts: 25
Mentor Respeitado
Topic starter
 

Postado por: @rakabr

Seja bem-vindo! Ótimo guia e muito bem organizado. 😉 

tmj man

 

 
Postado : 02/07/2025 6:59 pm
Compartilhar:

Anúncio