RTP Extractor
Autor: zecomeia | Publicado: 2011-02-04T15:28:00-02:00

RTP Extractorpor zecomeia
Introdução

Extrai para o seu projeto os arquivos do RTP que estão em uso no projeto. Isso evita ter que copiar o RTP inteiro para o seu projeto na hora da criação do disco de jogo, ou que o jogador precise ter o RTP instalado para poder jogar.

Características


Não sobre escreve arquivo de mesmo nome que exista na pasta do projeto.
O processo é rápido e pode ser acompanhado por uma barra de progresso.
Um arquivo(extract_log.txt) listando todos os arquivos copiados e seus respectivos tamanhos é gerado na pasta raiz do projeto.

Histórico

04/02/2011 v1.0.0
- Lançado o script

05/02/2011 v1.0.1
- Leitura do nome da DLL do projeto consertado
- Bug quando há mais de dois comandos "mover evento" na mesma página consertado


Como Usar

cole acima de Main
salve e execute o projeto
espere o processo de extração terminar
agora você já pode retirar o script do projeto

*O ideal é usá-lo antes de criar o disco de jogo, ou seja, quando o projeto estiver pronto para jogar, porque daí, teoricamente, nesse ponto o projeto não precisa mais ser alterado.

Script


#======================================================
# RTP Extractor
#------------------------------------------------------
#version: 1.0.1
#by:      zecomeia
#date:    05/01/2011
#for:     RGSS
#credits and thanks:
#- vgvgf (get path function from Aleworks Library)
#- Farenheight (justname and extension File methods
#[modified by me])
#- Rafidelis (get RGSS dll name funcion)
#- PLM (reported a bug)
#------------------------------------------------------
#more infos: http://colmeia-do-ze.co.cc
#tags: RTP, Extractor, RGSS
#------------------------------------------------------
#how to use:
#- paste above of Main script
#- save and play the project
#- wait exctraction end
#- now you can remove the script from your project
#
#*in project root folder will be generated an extract
#log(extract_log.txt) listing all files copied to the
#project
#==============http://colmeia-do-ze.co.cc==============

class File
 
  def self.ext(fname)
    fname = basename(fname)
    parts = fname.sub(/[^\.]*\./,'')
  end
 
  def self.justname(fname)
    basename(fname, "." + ext(fname))
  end

  def self.fcopy(src, dest)
    src = File.open(src, "rb")
    dest = File.new(dest,"wb")
    src.each_byte do |x|
      dest.putc(x)
    end
    dest.close
    src.close
  end

end

fini = File.open('Game.ini', 'r')
for line in fini.readlines
  if line =~ /Library=/
    GameDLL = File.justname($')
  end
end
fini.close

####vgvgf
RGSSGetRTPPath = Win32API.new(GameDLL, 'RGSSGetRTPPath', 'L', 'L')
RGSSGetPathWithRTP = Win32API.new(GameDLL, 'RGSSGetPathWithRTP', 'L', 'P')
def get_rtp_path(rtp = 0)
  RGSSGetPathWithRTP.call(RGSSGetRTPPath.call(rtp))
end
RGSSRTP_PATH = get_rtp_path(1)
####

module RTP_EXTRACTOR
  Data_actors        = load_data("Data/Actors.rxdata")
  Data_classes       = load_data("Data/Classes.rxdata")
  Data_skills        = load_data("Data/Skills.rxdata")
  Data_items         = load_data("Data/Items.rxdata")
  Data_weapons       = load_data("Data/Weapons.rxdata")
  Data_armors        = load_data("Data/Armors.rxdata")
  Data_enemies       = load_data("Data/Enemies.rxdata")
  Data_troops        = load_data("Data/Troops.rxdata")
  Data_states        = load_data("Data/States.rxdata")
  Data_animations    = load_data("Data/Animations.rxdata")
  Data_tilesets      = load_data("Data/Tilesets.rxdata")
  Data_common_events = load_data("Data/CommonEvents.rxdata")
  Data_system        = load_data("Data/System.rxdata")
  Data_mapinfos      = load_data("Data/MapInfos.rxdata")

  #Coisa de Preguiçoso XD
  ls = []
  Dir.foreach(RGSSRTP_PATH + "\\Graphics") { |x| ls.push(x) }
  ls.delete('.')
  ls.delete('..')
  ls.each do |x|
    str_eval = "#{x} = RGSSRTP_PATH + \"\\\\Graphics\\\\#{x}\""
    eval(str_eval)
  end
  ls = []
  Dir.foreach(RGSSRTP_PATH + "\\Audio") { |x| ls.push(x) }
  ls.delete('.')
  ls.delete('..')
  ls.each do |x|
    str_eval = "#{x} = RGSSRTP_PATH + \"\\\\Audio\\\\#{x}\""
    eval(str_eval)
  end
  #Coisa de preguiçoso END
end

class RTP_Extractor
 
  include RTP_EXTRACTOR
 
  attr_reader :files_size
  attr_reader :list
 
  def initialize()
    @files_size = 0
    @list = []
  end
 
  #list files in a folder
  #if ext = true the file extension print together
  def list_files(dir,ext=true)
    ls = []
    Dir.foreach(dir) {|x| ls.push(x) }
    ls.delete('.')
    ls.delete('..')
    if ext
      return(ls)
    else
      ls_noext = []
      ls.each { |x| ls_noext.push(File.justname(x)) }
      return(ls_noext)
    end
  end
 
  def map_events(map, file_list, command, move_command=[], parameter_204_0=false)
    code = command[0]
    parameter = command[1]
    misc_name = command[2]
    str_eval = "command.parameters\[#{parameter}\]#{misc_name}"
    unless move_command.empty?
      move_code = move_command[0]
      move_parameter = move_command[1]
      move_misc_name = move_command[2]
      move_str_eval = "mv_command.parameters\[#{move_parameter}\]#{move_misc_name}"
    end
    for event in map.events
      for page in event[1].pages
        if page.move_type == 3
          for pre_mv_command in page.move_route.list
            if pre_mv_command.code == move_code and !move_command.empty?
              fname = eval("pre_"+move_str_eval)
              unless file_list.include?(fname)
                file_list.push(fname)
              end
            end
          end
        end
        for command in page.list
          if command.code == 204
            if command.parameters[0] == parameter_204_0
              fname = eval(str_eval)
              unless file_list.include?(fname)
                file_list.push(fname)
              end
            end
          elsif command.code == 209 and !move_command.empty?
            for mv_command in command.parameters[1].list
              if mv_command.code == move_code
                fname = eval(move_str_eval)
                unless file_list.include?(fname)
                  file_list.push(fname)
                end
              end
            end
          elsif command.code == code
            fname = eval(str_eval)
            unless file_list.include?(fname)
              file_list.push(fname)
            end
          end
        end
      end
    end
  end
 
  def commons_events(file_list, command, move_command=[], parameter_204_0=false)
    code = command[0]
    parameter = command[1]
    misc_name = command[2]
    str_eval = "command.parameters\[#{parameter}\]#{misc_name}"
    unless move_command.empty?
      move_code = move_command[0]
      move_parameter = move_command[1]
      move_misc_name = move_command[2]
      move_str_eval = "mv_command.parameters\[#{move_parameter}\]#{move_misc_name}"
    end
    for command in Data_common_events[1].list     
      if command.code == 204
        if command.parameters[0] == parameter_204_0
          fname = eval(str_eval)
          unless file_list.include?(fname)
            file_list.push(fname)
          end
        end
      elsif command.code == 209 and !move_command.empty?
        for mv_command in command.parameters[1].list
          if mv_command.code == move_code
            fname = eval(move_str_eval)
            unless file_list.include?(fname)
              file_list.push(fname)
            end
          end
        end
      elsif command.code == code
        fname = eval(str_eval)
        unless file_list.include?(fname)
          file_list.push(fname)
        end
      end
    end
  end
 
  def troops_events(file_list, command, move_command=[], parameter_204_0=false)
    code = command[0]
    parameter = command[1]
    misc_name = command[2]
    str_eval = "command.parameters\[#{parameter}\]#{misc_name}"
    unless move_command.empty?
      move_code = move_command[0]
      move_parameter = move_command[1]
      move_misc_name = move_command[2]
      move_str_eval = "mv_command.parameters\[#{move_parameter}\]#{move_misc_name}"
    end
    for troop in Data_troops
      next if troop.nil?
      for page in troop.pages
        for command in page.list
          if command.code == 204
            if command.parameters[0] == parameter_204_0
              fname = eval(str_eval)
              unless file_list.include?(fname)
                file_list.push(fname)
              end
            end
          elsif command.code == 209 and !move_command.empty?
            for mv_command in command.parameters[1].list
              if mv_command.code == move_code
                fname = eval(move_str_eval)
                unless file_list.include?(fname)
                  file_list.push(fname)
                end
              end
            end
          elsif command.code == code
            fname = eval(str_eval)
            unless file_list.include?(fname)
              file_list.push(fname)
            end
          end
        end
      end
    end
  end
 
  def push_in(file_list, data, misc_name)
    for d in data
      next if d.nil?
      fname = eval("d#{misc_name}")
      unless file_list.include?(fname)
        file_list.push(fname)
      end
    end
  end
 
  #add to general file list
  def add2list(file_list, folder_in_path)
    ls = list_files(folder_in_path)
    ls_noext = list_files(folder_in_path, false)
    for name in file_list
      if ls_noext.include?(name)
        file_name = ls[ls_noext.index(name)]
        file = folder_in_path + "\\#{file_name}"
        @list.push(file)
      end
    end
  end
   
  #prepare the list os files to extract
  def extract_list()
     #######
    # AUDIO #
     #######
     
    #############################################
    #BGMs
   
    bgms = []   
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      bgms.push(map.bgm.name)
      map_events(map, bgms, [132, 0, '.name'])
      map_events(map, bgms, [241, 0, '.name'])
    end
    commons_events(bgms, [132, 0, '.name'])
    commons_events(bgms, [241, 0, '.name'])
    troops_events(bgms, [132, 0, '.name'])
    troops_events(bgms, [241, 0, '.name'])
    bgms.push(Data_system.title_bgm.name)
    bgms.push(Data_system.battle_bgm.name)
    add2list(bgms, BGM)
   
    #############################################
    #BGSs
   
    bgss = []
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      bgss.push(map.bgs.name)
      map_events(map, bgss, [245, 0, '.name'])
    end
    commons_events(bgss, [245, 0, '.name'])
    troops_events(bgss, [245, 0, '.name'])   
    add2list(bgss, BGS)
   
    #############################################
    #MEs
   
    mes = []   
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      map_events(map, mes, [133, 0, '.name'])
      map_events(map, mes, [249, 0, '.name'])
    end
    commons_events(mes, [133, 0, '.name'])
    commons_events(mes, [249, 0, '.name'])
    troops_events(mes, [133, 0, '.name'])
    troops_events(mes, [249, 0, '.name'])
    mes.push(Data_system.battle_end_me.name)
    mes.push(Data_system.gameover_me.name)
    add2list(mes, ME)
   
    #############################################
    #SEs
   
    ses = []
    push_in(ses, Data_items, ".menu_se.name")
    push_in(ses, Data_skills, ".menu_se.name")
    animations = Data_animations
    for i in 1...animations.size     
      for j in 0...animations[i].timings.size
        unless ses.include?(animations[i].timings[j].se.name)
          ses.push(animations[i].timings[j].se.name)
        end
      end
    end   
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      map_events(map, ses, [250, 0, '.name'], [44, 0, '.name'])
    end
    commons_events(ses, [250, 0, '.name'], [44, 0, '.name'])
    troops_events(ses, [250, 0, '.name'], [44, 0, '.name'])
    ses.push(Data_system.cursor_se.name)
    ses.push(Data_system.decision_se.name)
    ses.push(Data_system.cancel_se.name)
    ses.push(Data_system.buzzer_se.name)
    ses.push(Data_system.equip_se.name)
    ses.push(Data_system.shop_se.name)
    ses.push(Data_system.save_se.name)
    ses.push(Data_system.load_se.name)
    ses.push(Data_system.battle_start_se.name)
    ses.push(Data_system.escape_se.name)
    ses.push(Data_system.actor_collapse_se.name)
    ses.push(Data_system.enemy_collapse_se.name)
    add2list(ses, SE)

     ##########
    # GRAPHICS #
     ##########
   
    #############################################
    #Animations
   
    animations_names = []
    push_in(animations_names, Data_animations, ".animation_name")
    add2list(animations_names, Animations)
   
    #############################################
    #Autotiles
   
    autotiles_names = []
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      tileset = Data_tilesets[map.tileset_id]
      push_in(autotiles_names, tileset.autotile_names , "")
    end
    add2list(autotiles_names, Autotiles)
   
    #############################################
    #Battlebacks
   
    battlebacks_names = []
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      tileset = Data_tilesets[map.tileset_id]
      unless battlebacks_names.include?(tileset.battleback_name)
        battlebacks_names.push(tileset.battleback_name)
      end
      map_events(map, battlebacks_names, [204, 1, ''], [], 2)
    end
    commons_events(battlebacks_names, [204, 1, ''], [], 2)
    troops_events(battlebacks_names, [204, 1, ''], [], 2)
    add2list(battlebacks_names, Battlebacks)
   
    #############################################
    #Battlers
   
    battlers = []   
    push_in(battlers, Data_actors, ".battler_name")
    push_in(battlers, Data_enemies, ".battler_name")
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      map_events(map, battlers, [322, 3, ''])
    end
    commons_events(battlers, [322, 3, ''])
    troops_events(battlers, [322, 3, ''])
    add2list(battlers, Battlers)
   
    #############################################
    #Characters
   
    characters = []
    push_in(characters, Data_actors, ".character_name")
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      for event in map.events
        for page in event[1].pages
          unless characters.include?(page.graphic.character_name)
            characters.push(page.graphic.character_name)
          end
        end
      end
      map_events(map, characters, [322, 1, ''], [41, 0, ''])
    end
    commons_events(characters, [322, 1, ''], [41, 0, ''])
    troops_events(characters, [322, 1, ''], [41, 0, ''])
    add2list(characters, Characters)

    #############################################
    #Fogs
   
    fogs_names = []
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      tileset = Data_tilesets[map.tileset_id]
      unless fogs_names.include?(tileset.fog_name)
        fogs_names.push(tileset.fog_name)
      end
      map_events(map, fogs_names, [204, 1, ''], [], 1)
    end
    commons_events(fogs_names, [204, 1, ''], [], 1)
    troops_events(fogs_names, [204, 1, ''], [], 1)
    add2list(fogs_names, Fogs)
   
    #############################################
    #Gameovers
   
    gameover = [Data_system.gameover_name]
    add2list(gameover, Gameovers)
   
    #############################################
    #Icons
   
    icons = []
    push_in(icons, Data_skills, ".icon_name")
    push_in(icons, Data_items, ".icon_name")
    push_in(icons, Data_weapons, ".icon_name")
    push_in(icons, Data_armors, ".icon_name")
    add2list(icons, Icons)
   
    #############################################
    #Panoramas
   
    panoramas_names = []
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      tileset = Data_tilesets[map.tileset_id]
      unless panoramas_names.include?(tileset.panorama_name)
        panoramas_names.push(tileset.panorama_name)
      end
      map_events(map, panoramas_names, [204, 1, ''], [], 0)
    end
    commons_events(panoramas_names, [204, 1, ''], [], 0)
    troops_events(panoramas_names, [204, 1, ''], [], 0)
    add2list(panoramas_names, Panoramas)
   
    #############################################
    #Tilesets
   
    tilesets_names = []
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      tileset = Data_tilesets[map.tileset_id]
      unless tilesets_names.include?(tileset.tileset_name)
        tilesets_names.push(tileset.tileset_name)
      end
    end
    add2list(tilesets_names, Tilesets)
   
    #############################################
    #Titles
   
    title = [Data_system.title_name]
    add2list(title, Titles)
   
    #############################################
    #Transitions
   
    transitions = []
    transitions.push(Data_system.battle_transition)
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      map_events(map, transitions, [222, 0, ''])
    end
    commons_events(transitions, [222, 0, ''])
    troops_events(transitions, [222, 0, ''])
    add2list(transitions, Transitions)
   
    #############################################
    #Windowskins
   
    windowskins = []
    windowskins.push(Data_system.windowskin_name)
    for i in 1..Data_mapinfos.size
      map = load_data(sprintf("Data/Map%03d.rxdata", i))
      map_events(map, windowskins, [131, 0, ''])
    end
    commons_events(windowskins, [131, 0, ''])
    troops_events(windowskins, [131, 0, ''])
    add2list(windowskins, Windowskins)
   
    #delete match file between RTP and project
    #calculate the list data size
    for i in 0...@list.size
      dest = @list[i].dup
      dest.sub!("#{RGSSRTP_PATH}",'')
      if FileTest.exist?( ".#{dest}" )
        @list[i] = nil
      else       
        @files_size += FileTest.size(@list[i])
      end
    end
    #delete nil, empty and repeated from list
    @list.delete('')
    @list.compact!
    @list.uniq!
   
    return @list
  end
 
end

class Window_Progress < Window_Base
 
  def initialize(total_files_size)
    super(320-125, 240-60, 250, 110)
    self.contents = Bitmap.new(width - 32, height - 32)
        self.contents.font.name = 'Arial'
    self.contents.font.size = 20
    self.opacity = 0
    @total_files_size = total_files_size
    refresh()
  end
 
  def refresh(progress_string='', progress_files_size=0)
    return if @total_files_size == 0
    self.contents.clear
    self.contents.draw_text(4, 15, 220, 24, progress_string)
    self.contents.fill_rect(5,0,202,10,Color.new(200,200,200,200))
    self.contents.fill_rect(6,1,progress_files_size*200/@total_files_size,8,Color.new(0,0,200,200))
  end

end

rtp_extract = RTP_Extractor.new
print 'start'
flist = rtp_extract.extract_list()
total_files_size = rtp_extract.files_size
progress_files_size = 0
$game_system = load_data("Data/System.rxdata")
window_progress = Window_Progress.new(total_files_size)
$game_system = nil
n_files = 0
flog = File.new('extract_log.txt', 'a')
flog.puts('start...')
for src in flist
  dest = src.dup
  progress_string = 'copying ' + File.basename(dest)
  file_size = FileTest.size(dest)
  dest.sub!("#{RGSSRTP_PATH}",'')
  next if FileTest.exist?( ".#{dest}" )
  progress_files_size += file_size
  n_files += 1 
  window_progress.refresh(progress_string, progress_files_size)
  Graphics.update()
  File.fcopy(src, ".#{dest}" )
  str_log = ".#{dest} #{progress_files_size/1000} KB"
  flog.puts(str_log)
end
str_log = n_files.to_s+" files\n"+(progress_files_size/1000000).to_s+' MB('+(progress_files_size/1000).to_s+" KB)"
flog.puts(str_log)
flog.close
window_progress.dispose
print str_log
exit(0)


Créditos e Agradecimentos
Feito por zecomeia
vgvgf pela função para obter o path do RTP(retirado de seu script Aleworks Library)
Farenheight pelos métodos #justname e #extension(editei) da classe File
aos criadores do RMTool(programa que faz algo do tipo no RM2k) pela ideia
Rafidelis pelo código melhorado para obter o nome da dll do jogo
PLM por repotar bugs.