O TEMA DO FÓRUM ESTÁ EM MANUTENÇÃO. FEEDBACKS AQUI: ACESSAR

MS - Patch Automático

Iniciado por Brandt, 23/07/2015 às 03:43

[box class=titlebg]
MS - Patch Automático
[/box]

por Masked

[box class=titlebg]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=titlebg]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: auto:0
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=titlebg]Script[/box]
#==============================================================================
# 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=titlebg]Créditos e Agradecimentos[/box]
- a mim por criar.
~ Masked

Uou, ótimo script Masked, realmente pode ser muito útil, meus parabéns.

Coloca algumas screenshot pra etender melhor? .-.
Quero ver como é antes de baixar sakas? :será:

Então o script é excelente Masked, mas só uma duvida simples aqui como faço esse tal arquivo FTP ?
Eu to boiando nisso faz algum tempo já kkkk