Como fazer uma atualização automática de um cliente de jogo online

Neste artigo, falarei sobre como criei um sistema de atualização automática para um jogo de cliente online. Link para a fonte (Delphi) no final do artigo. Na verdade, eu implementei esse recurso nos meus dois jogos, e se a primeira panqueca sair um pouco irregular (no jogo Spectromancer), a segunda implementação será muito conveniente e eficaz. Este é o meu primeiro artigo sobre Habré, por isso não bata muito, mas aponte as falhas nos comentários :)

Algoritmo de atualização do jogo


  • Verificando a versão para atualização.
  • Baixe a lista de arquivos da versão atual.
  • Download de arquivos novos ou alterados para uma pasta temporária.
  • Instalando a atualização - trazendo os arquivos do cliente instalado de acordo com a lista.
  • Iniciando um cliente atualizado.

Verificação de versão


Antes de tudo, ao iniciar, o cliente solicita ao servidor o número da versão atual (X) e o número do mínimo permitido sem atualização (Y). Se a versão do cliente não for inferior a Y, não será necessária uma atualização; caso contrário, o cliente iniciará o utilitário de atualização " GetNewVersion.exe X " e será encerrado.

Como você pode ver, o número da versão é passado pelo parâmetro - isso permite atualizar o jogo para qualquer versão disponível no servidor e reduzi-lo ainda mais. Se o parâmetro não for passado, o próprio utilitário solicitará o número da versão atual do servidor. O número da versão é apenas um número inteiro, o esquema de numeração pode ser qualquer, por exemplo, minha versão 1.12 corresponde ao número 1120.

A resposta do servidor não vem instantaneamente e, antes de recebê-la, não podemos criar a janela do jogo, porque você pode fechá-la imediatamente, e as oscilações incompreensíveis na tela não são de todo o que precisamos. O tempo limite da resposta teria que levar algo, e o cliente está ocupado carregando / descompactando os JPEGs mais pesados. Você também não pode esperar muito: o jogador lançou o jogo - mas nada acontece na tela, uma bagunça. Portanto, se dentro de 1,0 s. a resposta do servidor não chegou - o carregamento do jogo continua da maneira usual. Isso não é grande coisa: assim que o jogador tentar fazer login no servidor, ele receberá uma mensagem sobre a necessidade de atualizar o cliente ou que o servidor está indisponível.

Baixar lista de arquivos


Sabendo o número da versão, o utilitário de atualização baixa a lista de arquivos em: [base_ur]>/[]/filelist
Esta é apenas uma lista de arquivos CSV com soma de verificação, bem como tamanhos compactados e descompactados, cada linha se parece com isso:
18*Priest.tga;1053151921D9;91719;107372
Aqui "18 *" significa que 18 caracteres no nome do arquivo são iguais ao arquivo anterior. Como os arquivos geralmente seguem em ordem alfabética e os caminhos podem ser longos - isso economiza significativamente o tamanho do arquivo da lista. Para um servidor Web no qual a compactação não está ativada, isso significa que o arquivo será baixado mais rapidamente e a atualização será iniciada mais cedo.

Baixar arquivos novos ou alterados


Não sabemos quantos anos o cliente do jogo tem, talvez alguns arquivos tenham sido alterados ou excluídos manualmente. Não queremos fazer download demais, portanto, após receber a lista de arquivos, o utilitário começa a verificá-los para atualizações: se o arquivo estiver faltando na pasta do jogo ou se sua soma de verificação for diferente, o arquivo será adicionado à fila de download. Ao mesmo tempo, não é possível carregar mais de 2 arquivos - isso é suficiente para que, por um lado, o download não diminua a velocidade, mas, por outro lado, ocorre sequencialmente.



Um tópico especial é a exibição do progresso. Até a lista inteira ter sido processada, não sabemos exatamente quantos arquivos baixar e qual o tamanho. No entanto, assim que o primeiro arquivo é carregado, já podemos exibir algumas informações. De fato, o progresso exibe a fila de downloads: quanto baixar e quanto já foi baixado.

Os arquivos baixados são descompactados imediatamente e salvos em uma pasta temporária. Eu uso a biblioteca zlib para compactação.

Quando a lista inteira de arquivos foi processada e todos os downloads foram concluídos, o utilitário verifica a presença do arquivo changes.txt e, se existir, o exibe. O usuário é solicitado a iniciar o procedimento de atualização. Antes de clicar no botão "Atualizar", ainda não foram feitas alterações na pasta do jogo. Assim, você pode optar por sair sem problemas.

A propósito, se o usuário interromper o download ou se recusar a instalar, na próxima vez em que ele não precisar baixar todos os arquivos novamente: antes de baixar o próximo arquivo, o utilitário verificará sua presença na pasta temporária e, se a soma de verificação corresponder, o download será considerado bem-sucedido.



Mas quando você clica em "Atualizar", o utilitário inicia outro utilitário - " InstallUpdate.exe " e é encerrado.

Instalar atualização


Por que preciso de outro utilitário? É simples: para atualizar os arquivos do jogo, você precisa executar com direitos de administrador. Mas baixar a atualização, pelo contrário, é contra-indicada. Porque, a menos que você seja um feliz proprietário de um certificado de assinatura de código EV, iniciar o processo com direitos de administrador exibirá a janela UAC. E se, ao iniciar o jogo, em vez da interface usual, o jogador vê o seguinte:



... então esse é, pelo menos, um motivo para tomar cuidado, ou mesmo abandonar completamente o lançamento. Outra coisa, com o consentimento manual para instalar a atualização - nesse contexto, a janela do UAC é percebida normalmente. Infelizmente, um processo no Windows não pode elevar seus direitos em tempo de execução - essa propriedade permanece inalterada desde o lançamento. Portanto, eu uso dois arquivos separados. De fato, GetNewVersion.exe e InstallUpdate.exe são o mesmo utilitário, os arquivos são idênticos. E a ação é determinada pelos parâmetros transmitidos e pelo nome do arquivo executável.

Portanto, ao ser iniciado, o InstallUpdate copia os arquivos do cliente do jogo da pasta temporária para a pasta do jogo e, em seguida, inicia o cliente atualizado e finaliza. Nesse caso, o arquivo GetNewVersion.exe também pode ser atualizado.

Todas as ações, bem como os erros que ocorrem, são registrados em detalhes no log, o que é muito útil para depuração.

O processo de preparação de uma nova versão


Examinamos o esquema de operação de atualização do ponto de vista do cliente do jogo, mas como fazer tudo funcionar? Para preparar novas compilações, escrevi outro utilitário - CompressBuild . Ele verifica recursivamente uma pasta, compacta arquivos usando o método Deflate e grava informações sobre eles na lista de filelist - lista de filelist . Após a compactação, o símbolo "_" é anexado ao nome do arquivo. Os arquivos compactados não são compactados novamente; portanto, se necessário, somente arquivos individuais podem ser atualizados na pasta de compilação; o CompressBuild os atualizará apenas.

Alguns arquivos no cliente do jogo mudam durante a operação, por exemplo, contêm configurações. Esses arquivos devem ser ignorados, o utilitário pega os modelos apropriados no arquivo de exclusão. Ou seja, esses arquivos simplesmente não entram na lista de filelist e não se deterioram no cliente durante a atualização.

Assim, para preparar uma nova compilação, preciso:

1. Copie a pasta \master para \[_]
2. Execute o CompressBuild , que compactará os arquivos e fará uma lista deles.
3. Carregue tudo no site do jogo.
4. Altere no servidor do jogo o número da versão atual para o número que acabou de baixar. Voila!

A partir de agora, ao atualizar as pessoas, receberá uma nova versão.

Bem, pastas com versões antigas no servidor podem ser excluídas para não ocupar espaço.

Conclusão


Obviamente, meu sistema de atualização não é perfeito e não apresenta falhas. Por exemplo, se um arquivo foi excluído no cliente, ele permanecerá com os players. Se o arquivo tiver sido renomeado, ele será baixado como novo e a instância antiga não será excluída. Você pode, é claro, refinar o utilitário de atualização adicionando comandos para excluir / renomear arquivos à lista de arquivos, mas, em geral, esses problemas não são relevantes para o meu jogo, então não me incomodei.

Bem, você pode obter a fonte aqui: astralheroes.com/files/UpdaterSrc.zip
(compilado no Delphi-2006 / Turbo Delphi, não posso garantir outros compiladores).

Source: https://habr.com/ru/post/pt423207/


All Articles