🤔 Para Refletir : "CHAR armazena um valor alfanumérico à variável. Programar, por si só, armazena bugs à constante." - DougMR

MS - Patch Automático[VX Ace]

Colaboração Colaboração
Quod erat demonstrandum
Postagens
337
Bravecoins
1.156
[box class=calendar_today]
MS - Patch Automático​
[/box]

por Masked

[box class=calendar_today]Características[/box]
Esse script funciona mais ou menos como os patchers de jogos online, toda vez que o jogo inicia ele abre uma cena onde é verificada se a versão atual do jogo é menor que a disponível no servidor (através de um arquivo pré-configurado) e baixa os arquivos necessários se o jogo estiver desatualizado.
Minha sugestão é que você use o meu script de DLC, assim é possível baixar tudo por um só arquivo e ainda por cima comprimir e encriptar ele, mas você pode usar o script pra baixar qualquer tipo de arquivo.

[box class=calendar_today]Instruções[/box]
Primeiro, você precisa de um lugar para hospedar seus arquivos, pode ser qualquer servidor, desses gratuitos mesmo.
Escolhido o site onde ficarão os arquivos, use FTP para criar um arquivo 'version' na pasta raíz dele. Esse será o arquivo que guiará o script, depois de criado você deve copiar o endereço completo para ele na constante 'URL' no script (linha 23). Note que é necessário usar www em alguns sites para que funcione corretamente.

O arquivo deve ter, na primeira linha, o número da versão atual, para comparação com a versão configurada no script. As linhas seguintes devem seguir este modelo:
Código:
http://www.urldosite.com.br/arquivo_a_ser_baixado arquivo-de-destino.extenção
Isso fará com que o script baixe o arquivo 'http://www.urldosite.com.br/arquivo_a_ser_baixado'na pasta do jogo com o nome 'arquivo-de-destino.extensão' (lembre-se que você precisa salvar o arquivo no site para que isso aconteça, no entanto).

Fora isso, você só precisa configurar a cena nas configurações do script.

[box class=calendar_today]Screenshots[/box]
KWu935n.png


[box class=calendar_today]Script[/box]
Código:
#==============================================================================
# MS - Auto Patch
#------------------------------------------------------------------------------
# por Masked
#==============================================================================
($imported ||= {})[:mbs_auto_patch] = true
#==============================================================================
# ** MBS
#==============================================================================
module MBS
  #============================================================================
  # ** AutoPatch
  #============================================================================
  module AutoPatch
    #==========================================================================
    # Configurações
    #==========================================================================
    #------------------------------------------------------------------------
    # Patch
    #------------------------------------------------------------------------
    # Link do arquivo com a versão atual do jogo e os links para os arquivos
    # que devem ser baixados
    URL     = 'http://www.urlaleatorio.com.br/version'
    # Versão baixada do jogo (altere esse valor quando atualizar o jogo)
    VERSION = 1.00
    #------------------------------------------------------------------------
    # Cena
    #------------------------------------------------------------------------
    # Imagens de fundo na pasta Graphics separadas por vírgulas, o script 
    # seleciona uma imagem aleatoriamente cada vez que o jogo começa.
    # nil para usar cor
    BACKGROUND  = ['Pictures/PatchBackground']
    # Cor de fundo
    BACK_COLOR  = Color.new(100,125,255)
    
    # Texto mostrado enquanto verifica a existência de atualizações
    TEXT_VERSION_CHECK = 'Procurando atualizações...'
    # Texto mostrado enquanto baixa o arquivo
    TEXT_DOWNLOADING   = 'Baixando atualizações...'
    
    # Posição do texto (X, Y)
    TEXT_POSITION = [0, Graphics.height - 96]
    
    # Caso queira que janelas de mensagens avisem quando houver um erro deixe
    # como true, se não, deixe como false
    SHOW_ERRORS = true
    
    # Imagem da barra de fundo na pasta Graphics (a 1ª metade deve ser o fundo 
    # e a 2ª a parte da frente), nil para usar cor
    LOADING_BAR = 'Pictures/LoadingBar'
    # Cores da barra de carregamento (a 1ª é a cor do fundo e a 2ª é a cor da
    # frente. nil para não usar barra de carregamento
    LOADING_COLORS = [Color.new(255,255,255),Color.new(0,255,50)]
    # Posição da barra de carregamento
    LOADING_POSITION  = [0,416 - 48]
    # Largura e altura da barra quando for usar cores
    LOADING_DIMENSION = [544, 32]
    #==========================================================================
    # Fim das Configurações
    #==========================================================================
    @@_version = nil
    @@_outdated = nil
    #------------------------------------------------------------------------
    # * API
    #------------------------------------------------------------------------
    InternetGetConnectedState = Win32API.new('wininet.dll','InternetGetConnectedState','pl','i')
    URLDownloadToFile = Win32API.new('urlmon.dll','URLDownloadToFileA','pppli','l')
    #------------------------------------------------------------------------
    # * Verificação de conexão com a internet
    #------------------------------------------------------------------------
    def self.connected?
      return InternetGetConnectedState.call(' ',0) == 1
    end
    #------------------------------------------------------------------------
    # * Verificação de se o jogo está desatualizado
    #------------------------------------------------------------------------
    def self.outdated?
      raise('Erro ao verificar versão: Falha ao se conectar à internet') unless connected?
      return @@_outdaded unless @@_outdated.nil?
      r = rand(0x7FFFF)
      Dir.mkdir "#{ENV['TMP']}/game#{r.to_s(16)}"
      hresult = URLDownloadToFile.call(nil,URL,"#{ENV['TMP']}/game#{r.to_s(16)}/version",0,0)
      unless hresult == 0
        Dir.delete("#{ENV['TMP']}/game#{r.to_s(16)}")
        raise(sprintf('Erro ao verificar versão: HRESULT 0x%X', hresult)) 
      end
      content = ''
      File.open("#{ENV['TMP']}/game#{r.to_s(16)}/version",'rb') do |file|
        content = file.read
      end
      @@_version = content.split("\n")
      v = @@_version.shift.to_f
      File.delete("#{ENV['TMP']}/game#{r.to_s(16)}/version")
      Dir.delete("#{ENV['TMP']}/game#{r.to_s(16)}")
      return v > VERSION
    end
    #------------------------------------------------------------------------
    # * Aquisição dos arquivos necessários para a atualização
    #------------------------------------------------------------------------
    def self.needed_files
      return [] unless self.outdated?
      return @@_version
    end
    #------------------------------------------------------------------------
    # * Download do arquivo de atualização
    #------------------------------------------------------------------------
    def self.download(url, dest)
      return unless connected?
      hresult = URLDownloadToFile.call(nil,url,"#{Dir.pwd}/#{dest}",0,0)
      return msgbox(sprintf('Erro ao atualizar: HRESULT 0x%X', hresult)) unless hresult == 0
    end
  end
end
#==============================================================================
# ** Sprite_Progress
#------------------------------------------------------------------------------
# Esta é a classe dos sprites de barra de progresso
#==============================================================================
class Sprite_Progress < Sprite
  #--------------------------------------------------------------------------
  # * Definição dos atributos
  #--------------------------------------------------------------------------
  attr_accessor :source
  attr_reader :progress
  #--------------------------------------------------------------------------
  # * Inicialização do objeto
  #--------------------------------------------------------------------------
  def initialize(viewport=nil)
    super
    @progress = 0.0
  end
  #--------------------------------------------------------------------------
  # * Atualização do objeto
  #--------------------------------------------------------------------------
  def update
    super
    @progress = 100.0 if @progress > 100.0
    @progress = 0.0   if @progress < 0.0
    refresh if @progress != @_old
  end
  #--------------------------------------------------------------------------
  # * Definição do sprite do bitmap
  #--------------------------------------------------------------------------
  def bitmap=(bit)
    super
    refresh
  end
  #--------------------------------------------------------------------------
  # * Definição do progresso da barra
  #--------------------------------------------------------------------------
  def progress=(n)
    @progress = n.to_f
    refresh
  end
  #--------------------------------------------------------------------------
  # * Redesenho do sprite
  #--------------------------------------------------------------------------
  def refresh
    @_old = @progress
    self.bitmap.clear
    
    bg_rect = Rect.new(0,0,source.width/2,source.height)
    self.bitmap.blt(0,0,source,bg_rect)
    
    w = source.width/2
    fg_rect = Rect.new(source.width/2,0,(w*@progress/100.0).to_i,source.height)
    self.bitmap.blt(0,0,source,fg_rect)
    
    self.bitmap.font.size = self.bitmap.height
    self.bitmap.draw_text(self.bitmap.rect,"#{@progress.truncate}% ",2)
  end
end
#==============================================================================
# ** Scene_Patch
#------------------------------------------------------------------------------
# Esta é a cena onde o jogo atualiza
#==============================================================================
class Scene_Patch < Scene_Base
  include MBS::AutoPatch
  #--------------------------------------------------------------------------
  # Velocidade máxima com que a barra de progresso aumenta
  #--------------------------------------------------------------------------
  SPEED = 2
  #--------------------------------------------------------------------------
  # * Inicialização do processo
  #--------------------------------------------------------------------------
  def start
    super
    create_background
    create_text
    create_loadbar
    Graphics.update
    Graphics.wait(5)
    begin
      @need_update = MBS::AutoPatch.outdated?
      @progress = 0.0
      catch(:exit) do
        throw(:exit) unless @need_update
        @text.bitmap.clear
        @text.bitmap.draw_text(0,0,@text.width,@text.height,TEXT_DOWNLOADING)
        update
        @files = MBS::AutoPatch.needed_files
        throw(:exit) if @files.size == 0
        @step = 100/@files.size
        @files.each do |file|
          s = file.split(' ')
          MBS::AutoPatch.download(s[0], s[1..-1].join(''))
          @progress = @loading.progress
          draw_progress
        end
      end
      @progress = 100.0
      @step = 100.0
      draw_progress
      Graphics.wait(30)
    rescue
      msgbox($!) if SHOW_ERRORS
    end
    SceneManager.call(SceneManager.first_scene_class)
  end
  #--------------------------------------------------------------------------
  # * Atualização do progresso da barra
  #--------------------------------------------------------------------------
  def draw_progress
    until @loading.progress >= (@progress + @step > 100 ? 100 : @progress + @step)
      @loading.progress += @step > SPEED ? SPEED : @step
      update
    end
  end
  #--------------------------------------------------------------------------
  # * Criação do fundo da cena
  #--------------------------------------------------------------------------
  def create_background
    @background = Sprite.new
    if BACKGROUND
      @background.bitmap = Bitmap.new("Graphics/#{BACKGROUND[rand(BACKGROUND.size-1)]}")
    else
      @background.bitmap = Bitmap.new(Graphics.width,Graphics.height)
      @background.bitmap.fill_rect(0,0,Graphics.width,Graphics.height,BACK_COLOR)
    end
  end
  #--------------------------------------------------------------------------
  # * Criação do sprite com o texto
  #--------------------------------------------------------------------------
  def create_text
    @text = Sprite.new
    @text.bitmap = Bitmap.new(Graphics.width,32)
    @text.bitmap.draw_text(0,0,@text.width,@text.height,TEXT_VERSION_CHECK)
    @text.x,@text.y=TEXT_POSITION
  end
  #--------------------------------------------------------------------------
  # * Criação da barra de carregamento
  #--------------------------------------------------------------------------
  def create_loadbar
    @loading = Sprite_Progress.new
    if LOADING_BAR
      @loading.source = Bitmap.new("Graphics/#{LOADING_BAR}")
      @loading.bitmap = Bitmap.new(@loading.source.width/2,@loading.source.height)
    elsif LOADING_COLORS
      source = Bitmap.new(LOADING_DIMENSION[0] * 2, LOADING_DIMENSION[1])
      source.fill_rect(0,0,source.width/2,source.height,LOADING_COLORS[0])
      source.fill_rect(source.width/2,0,source.width/2,source.height,LOADING_COLORS[1])
      @loading.source = source
      @loading.bitmap = Bitmap.new(*LOADING_DIMENSION)
    end
    @loading.x,@loading.y=*LOADING_POSITION
  end
  #--------------------------------------------------------------------------
  # * Atualização do processo
  #--------------------------------------------------------------------------
  def update
    super
    @loading.update
  end
  #--------------------------------------------------------------------------
  # * Finalização do processo
  #--------------------------------------------------------------------------
  def terminate
    super
    @background.dispose
    @text.dispose
    @loading.dispose
  end
end
#==============================================================================
# ** SceneManager
#------------------------------------------------------------------------------
# Este módulo controla as cenas do jogo
#==============================================================================
module SceneManager
  #--------------------------------------------------------------------------
  # * Execução
  #--------------------------------------------------------------------------
  def self.run
    DataManager.init
    Audio.setup_midi if use_midi?
    @scene = Scene_Patch.new
    @scene.main while @scene
  end
end

[box class=calendar_today]Créditos e Agradecimentos[/box]
- a mim por criar.
 
Mas esse Masked tá muito rápido. Falou do script ontem e já postou hoje.
Tá virando Ninja? HAHAH
Esse script além de muito útil é muito incrível *-*
Será ótimo atualizar o jogo sem a necessidade de upar ele todo novamente.
Senti alta de um Print mostrando como é o Patch. Poderia adicionar kkk
Não temo como testar agora, então ficarei na curiosidade u.u
 
[member=3]RyanKamos[/member]: Hehe, eu não perco tempo não cara :-_-:

Valeu, tomara que ajude o/
Eu ia postar com as imagens que eu usei pra cena em anexo, mas o condado só acheita até 128kb, aí não foi ;-;. Aí como na hora tava meio com sono acabei não upando elas, assim que der eu posto umas screens.
 
Caramba, isso vai cair como uma luva, ainda mais para mim que vou atualizar bastante meu projeto. Vou testar como funciona... Parabéns Asiático Masked!  :palmas:
 
Caramba cara! Esse Script vai ser a revolução de muitos jogos *-*- kkkk Mas é serio isso cai como uma luva em muitos projetos e da um tom mais profissional e facilita a vida do jogador.

 
Voltar
Topo