Advertisement
Guest User

MBS - Event Export Base

a guest
Aug 21st, 2015
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 15.72 KB | None | 0 0
  1. #==============================================================================
  2. # MBS - Event Export
  3. #------------------------------------------------------------------------------
  4. # por Masked
  5. #==============================================================================
  6. ($imported ||= {})[:mbs_event_export] = true
  7. #==============================================================================
  8. # * Verificação
  9. #==============================================================================
  10. unless $imported[:mbs_event_export_adapter]
  11.   raise "MBS - Event Export: É necessário usar um módulo de adaptação para a engine que estiver usando."
  12. end
  13. #==============================================================================
  14. # ** MBS::EventExport
  15. #------------------------------------------------------------------------------
  16. # Este módulo controla a exportação
  17. #==============================================================================
  18. module MBS::EventExport
  19.    
  20.   #---------------------------------------------------------------------------
  21.   # Versão [Maior, Menor]
  22.   #
  23.   # Alterações na versão maior implicam que o script não funciona em versões
  24.   # anteriores
  25.   #---------------------------------------------------------------------------
  26.   VERSION = [1, 0]
  27.  
  28.   #---------------------------------------------------------------------------
  29.   # Marcações do arquivo
  30.   #
  31.   # Ajudam a organizar o arquivo
  32.   #---------------------------------------------------------------------------
  33.   # Identifica o arquivo
  34.   MAGIC   = 'PEvF'
  35.   # Identifica um começo de página
  36.   PAGE    = '^'
  37.   # Identifica um começo de comando
  38.   CMD     = '@'
  39.   # Identifica um chunk de dados
  40.   DATA    = '!'
  41.   # Fim do arquivo
  42.   EOF     = ';'
  43.   #---------------------------------------------------------------------------
  44.   module_function
  45.   #---------------------------------------------------------------------------
  46.   # * Escrita do evento para um arquivo
  47.   #     arg      : Argumento que identifica o evento
  48.   #     filename : Nome do arquivo de destino
  49.   #---------------------------------------------------------------------------
  50.   def export_event(arg, filename)
  51.     begin
  52.       file = File.open(filename, 'wb')
  53.    
  54.       # Aquisição do RPG::Event equivalente ao argumento passado
  55.       if arg.is_a?(Game_Event)
  56.         event = arg.instance_variable_get(:@event)
  57.       elsif arg.is_a?(Integer)
  58.         event = $game_map.events[arg].instance_variable_get(:@event)
  59.       elsif arg.is_a?(RPG::Event)
  60.         event = a
  61.       else
  62.         raise ArgumentError.new('Invalid argument')
  63.       end
  64.      
  65.       # Escrita do cabeçalho do arquivo
  66.       Writer.write_header(event, file)
  67.      
  68.       # Escrita de cada comando de cada página no arquivo
  69.       Writer.write_pages(event, file)
  70.      
  71.       file.write(EOF)
  72.     ensure
  73.       file.close
  74.     end
  75.   end
  76.   #--------------------------------------------------------------------------
  77.   # * Importação de um evento
  78.   #     filename : Nome do arquivo onde o evento está
  79.   #--------------------------------------------------------------------------
  80.   def import_event(filename)
  81.     file = File.open(filename, 'rb')
  82.     event = RPG::Event.new(0,0)
  83.     event.pages = []
  84.     begin
  85.       Reader.read_header(event, file)
  86.       Reader.read_pages(event, file)
  87.     ensure
  88.       file.close
  89.     end
  90.     return event
  91.   end
  92. end
  93. #==============================================================================
  94. # ** MBS::EventExport::Writer
  95. #------------------------------------------------------------------------------
  96. # Este é o módulo responsável pela escrita no arquivo
  97. #==============================================================================
  98. module MBS::EventExport::Writer
  99.   include MBS::EventExport
  100.   module_function
  101.   #---------------------------------------------------------------------------
  102.   # * Escrita de dados para um arquivo
  103.   #     data : Os dados a serem escritos
  104.   #     file : O arquivo onde os dados serão escritos
  105.   #---------------------------------------------------------------------------
  106.   def write_data(data, file)
  107.     file.write(DATA)
  108.     if data.nil?
  109.       file.write([0].pack('L'))
  110.     else
  111.       data = data.to_s
  112.       file.write([data.size].pack('L'))
  113.       file.write(data)
  114.     end
  115.   end
  116.   #---------------------------------------------------------------------------
  117.   # * Escrita do cabeçalho do arquivo
  118.   #     event : Evento sendo exportado
  119.   #     file  : Arquivo de destino
  120.   #---------------------------------------------------------------------------
  121.   def write_header(event, file)
  122.     # Mágica
  123.     file.write(MAGIC)
  124.     # Versão
  125.     file.write(VERSION.pack('CC'))
  126.     # ID do evento
  127.     write_data([event.id].pack('L'), file)
  128.     # Nome do evento
  129.     write_data(event.name,file)
  130.     # X e Y do evento
  131.     write_data([event.x,event.y].pack('LL'), file)
  132.     # Fim de lote
  133.     write_data(nil,file)
  134.   end
  135.   #---------------------------------------------------------------------------
  136.   # * Escrita das páginas do evento para o arquivo
  137.   #     event : Evento sendo exportado
  138.   #     file  : Arquivo de destino
  139.   #---------------------------------------------------------------------------
  140.   def write_pages(event, file)
  141.     event.pages.each do |page|
  142.       write_page_header(page, file)
  143.       page.list.each do |command|
  144.         write_command(command, file)
  145.       end
  146.       write_data(nil, file)
  147.     end
  148.   end
  149.   #---------------------------------------------------------------------------
  150.   # * Aquisição de um integer a partir de uma array de bools
  151.   #     bools : Lista de até 8 booleanos
  152.   #---------------------------------------------------------------------------
  153.   def pack_bool(*bools)
  154.     x = 8
  155.     return bools.inject(0) do |r, v|
  156.       x -= 1
  157.       r + (v ? 1 : 0) * (2**x)
  158.     end
  159.   end
  160.   #---------------------------------------------------------------------------
  161.   # * Escrita do cabeçalho da página num arquivo
  162.   #     page : Página do evento sendo exportado
  163.   #     file : Arquivo de destino
  164.   #---------------------------------------------------------------------------
  165.   def write_page_header(page, file)
  166.     # Mágica
  167.     file.write(PAGE)
  168.    
  169.     # Condições da página
  170.     c = page.condition
  171.     i = pack_bool(c.switch1_valid,c.switch2_valid,c.variable_valid,
  172.         c.self_switch_valid, RGSS > 1 ? c.item_valid : false, RGSS > 1 ? c.actor_valid : false)
  173.  
  174.     write_data(i.chr, file)
  175.     write_data([c.switch1_id, c.switch2_id, c.variable_id, c.variable_value].pack('S4'),file)
  176.     write_data(c.self_switch_ch, file)
  177.     write_data([RGSS > 1 ? c.item_id : 1, RGSS > 1 ? c.actor_id : 1].pack('SS'), file)
  178.    
  179.     # Gráfico da página
  180.     g = page.graphic
  181.     write_data([g.tile_id].pack('S'), file)
  182.     write_data(g.character_name, file)
  183.     write_data([RGSS > 1 ? g.character_index : 0,g.direction,g.pattern].pack('C3'), file)
  184.    
  185.     # Movimento
  186.     write_data([page.move_type,page.move_speed,page.move_frequency].pack('C3'), file)
  187.     write_data(move_route(page.move_route), file)
  188.    
  189.     # Propriedades da página
  190.     i = pack_bool(page.walk_anime,page.step_anime,page.direction_fix,page.through)
  191.     if RGSS > 1
  192.       i += page.priority_type & 0b11
  193.     else
  194.       i += page.always_on_top ? 3 : 0
  195.     end
  196.     write_data([i,page.trigger].pack('CC'), file)
  197.      
  198.     # Fim de lote
  199.     write_data(nil,file)
  200.   end
  201.   #---------------------------------------------------------------------------
  202.   # * Conversão de uma rota de movimento em texto
  203.   #     route : Rota de movimento
  204.   #---------------------------------------------------------------------------
  205.   def move_route(route)
  206.     result = ""
  207.     i = pack_bool(route.repeat, route.skippable, RGSS > 1 ? route.wait : false)
  208.     result << i.chr
  209.    
  210.     route.list.each do |command|
  211.       result << DATA
  212.       params = command.parameters.collect do |param|
  213.         Marshal.dump(param)
  214.       end
  215.       params << Marshal.dump(nil)
  216.       par_str = params.inject('') do |r, v|
  217.         r += [v.size].pack('S')
  218.         r += v
  219.       end
  220.       result << [par_str.size + 2].pack('S')
  221.       result << [MBS::EventExport.move_command(command.code)].pack('S')
  222.       result << par_str
  223.     end
  224.    
  225.     result
  226.   end
  227.   #---------------------------------------------------------------------------
  228.   # * Escrita do comando num arquivo
  229.   #     command : Comando do evento sendo exportado
  230.   #     file    : Arquivo de destino
  231.   #---------------------------------------------------------------------------
  232.   def write_command(command, file)
  233.     # Mágica
  234.     file.write(CMD)
  235.    
  236.     # Código do comando
  237.     write_data([MBS::EventExport.command(command.code), command.indent].pack('SC'), file)
  238.    
  239.     # Parâmetros do comando
  240.     command.parameters.each do |param|
  241.       write_data(Marshal.dump(param), file)
  242.     end
  243.    
  244.     # Fim de lote
  245.     write_data(nil,file)
  246.   end
  247. end
  248. #==============================================================================
  249. # ** MBS::EventExport::Reader
  250. #------------------------------------------------------------------------------
  251. # Este é o módulo responsável pela leitura do arquivo
  252. #==============================================================================
  253. module MBS::EventExport::Reader
  254.   include MBS::EventExport
  255.   module_function
  256.   #--------------------------------------------------------------------------
  257.   # * Leitura de dados do arquivo
  258.   #     file : Arquivo de onde os dados serão lidos
  259.   #--------------------------------------------------------------------------
  260.   def read_data(file)
  261.     raise IOError.new('Invalid data chunk') unless file.read(1) == DATA
  262.     size = file.read(4).unpack('L')[0]
  263.     return nil if size == 0
  264.     result = file.read(size)
  265.     return result
  266.   end
  267.   #--------------------------------------------------------------------------
  268.   # * Leitura do cabeçalho do arquivo
  269.   #     event : Evento de destino
  270.   #     file  : Arquivo-fonte do evento
  271.   #--------------------------------------------------------------------------
  272.   def read_header(event, file)
  273.     # Mágica
  274.     raise IOError.new('Invalid event file') unless file.read(4) == MAGIC
  275.     # Versão
  276.     version = file.read(2).unpack('CC')
  277.     raise 'Incompatible event file version' unless version[0] == VERSION[0]
  278.     raise 'Incompatible event file version' if version[1] > VERSION[1]
  279.     # ID, nome e XY
  280.     event.id = read_data(file).unpack('L')[0]
  281.     event.name = read_data(file)
  282.     event.x, event.y = *read_data(file).unpack('LL')
  283.    
  284.     read_data(file)
  285.   end
  286.   #--------------------------------------------------------------------------
  287.   # * Leitura das páginas do evento
  288.   #     event : Evento de destino
  289.   #     file  : Arquivo-fonte do evento
  290.   #--------------------------------------------------------------------------
  291.   def read_pages(event, file)
  292.     until (c = file.read(1)) == EOF || file.eof?
  293.       if c == PAGE
  294.         file.pos -= 1
  295.         page = RPG::Event::Page.new
  296.         read_page_header(page, file)
  297.         until file.eof?
  298.           c = file.read(1)
  299.           if c == CMD
  300.             file.pos -= 1
  301.             page.list << read_command(file)
  302.           else
  303.             file.pos -= 1
  304.             break if read_data(file) == nil
  305.           end
  306.         end
  307.         event.pages << page
  308.       end
  309.     end
  310.   end
  311.   #--------------------------------------------------------------------------
  312.   # * Aquisição de uma array de booleans por um int
  313.   #     n : Número a ser dividido em 8 booleanos
  314.   #--------------------------------------------------------------------------
  315.   def unpack_int(n)
  316.     return [] if n == 0
  317.     bits = 8
  318.     x = 8
  319.     ary  = Array.new(bits, false)
  320.     for i in 0..bits
  321.       x -= 1
  322.       ary[i] = n & (1 * (2**x)) != 0
  323.     end
  324.     ary
  325.   end
  326.   #---------------------------------------------------------------------------
  327.   # * Conversão de um texto em rota de movimento
  328.   #     str : Texto a ser convertido
  329.   #---------------------------------------------------------------------------
  330.   def move_route(str)
  331.     route = RPG::MoveRoute.new
  332.     route.list = []
  333.     if RGSS == 3
  334.       route.repeat, route.skippable, route.wait = *unpack_int(str[0].unpack('C')[0])
  335.     elsif RGSS == 2
  336.       route.repeat, route.skippable, route.wait = *unpack_int(str[0].chr.unpack('C')[0])
  337.     else
  338.       route.repeat, route.skippable, w = *unpack_int(str[0].chr.unpack('C')[0])
  339.     end
  340.     str = str[1..(str.size-1)]
  341.    
  342.     while (RGSS == 3 ? str[0] : str[0].to_i.chr) == DATA
  343.       size = str[1..2].unpack('S')[0]
  344.       data = str[3,size]
  345.       command = RPG::MoveCommand.new
  346.       command.code = MBS::EventExport.move_command(data[0..1].unpack('S')[0])
  347.       data = data[2..(data.size-1)]
  348.       params = []
  349.       par = 0
  350.       i = 0
  351.       until par.nil?
  352.         par_sz = data[i,2].unpack('S')[0]
  353.         par = Marshal.load(data[i+2,par_sz])
  354.         params << par
  355.         i += par_sz + 2
  356.       end
  357.       command.parameters = params[0...(data.size-1)]
  358.       route.list << command
  359.       str = str[(size+3)..(str.size-1)]
  360.     end
  361.    
  362.     route
  363.   end
  364.   #--------------------------------------------------------------------------
  365.   # * Leitura do cabeçalho da página
  366.   #     page : Página do evento de destino
  367.   #     file : Arquivo-fonte do evento
  368.   #--------------------------------------------------------------------------
  369.   def read_page_header(page, file)
  370.     # Mágica
  371.     raise IOError.new('Invalid page header') unless file.read(1) == PAGE
  372.    
  373.     # Condição
  374.     page.condition = RPG::Event::Page::Condition.new
  375.     bools = unpack_int(read_data(file).unpack('C')[0])
  376.     bools += [false] * (6 - bools.size)
  377.    
  378.     c = page.condition
  379.     if RGSS > 1
  380.       c.switch1_valid,c.switch2_valid,c.variable_valid,c.self_switch_valid,c.item_valid,c.actor_valid = *bools
  381.     else
  382.       c.switch1_valid,c.switch2_valid,c.variable_valid,c.self_switch_valid,iv,av = *bools
  383.     end
  384.     ids = read_data(file).unpack('S4')
  385.     c.switch1_id,c.switch2_id,c.variable_id,c.variable_value = *ids
  386.     ch = read_data(file)
  387.     c.self_switch_ch = ch
  388.     ids = read_data(file).unpack('SS')
  389.     if RGSS > 1
  390.       c.item_id,c.actor_id = *ids
  391.     else
  392.       iid,aid = *ids
  393.     end
  394.    
  395.     # Graphics
  396.     page.graphic = RPG::Event::Page::Graphic.new
  397.    
  398.     g = page.graphic
  399.     g.tile_id = read_data(file).unpack('S')[0]
  400.     g.character_name = read_data(file)
  401.     if RGSS > 1
  402.       g.character_index,g.direction,g.pattern = *read_data(file).unpack('C3')
  403.     else
  404.       ci,g.direction,g.pattern = *read_data(file).unpack('C3')
  405.     end
  406.     # Movimento
  407.     page.move_type,page.move_speed,page.move_frequency = *read_data(file).unpack('C3')
  408.     page.move_route = move_route(read_data(file))
  409.    
  410.     # Propriedades da página
  411.     i,page.trigger = read_data(file).unpack('CC')
  412.     page.walk_anime,page.step_anime,page.direction_fix,page.through = *unpack_int(i & 0b11111100)
  413.     if RGSS > 1
  414.       page.priority_type = i & 0b11
  415.     elsif i & 0b11 == 3
  416.       page.always_on_top = true
  417.     end
  418.      
  419.     # Fim de lote
  420.     read_data(file)
  421.   end
  422.   #--------------------------------------------------------------------------
  423.   # * Leitura do chunk de comando
  424.   #     file : Arquivo-fonte do evento
  425.   #--------------------------------------------------------------------------
  426.   def read_command(file)
  427.     # Mágica
  428.     raise IOError.new('Invalid command chunk') unless file.read(1) == CMD
  429.    
  430.     # Código e identação do comando
  431.     command = RPG::EventCommand.new
  432.     command.code, command.indent = *read_data(file).unpack('SC')
  433.     command.code = MBS::EventExport.to_command(command.code)
  434.    
  435.     # Parâmetros
  436.     until (obj = read_data(file)) == nil
  437.       command.parameters << Marshal.load(obj)
  438.     end
  439.    
  440.     command
  441.   end
  442. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement