# # gamedataloader.rb # Game Data Loader # # Author:: David Muir # Date:: 28 February 2008 # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'pipeline/config/projects' require 'pipeline/content/content_core' require 'pipeline/content/content_maps' require 'pipeline/game/mapidefile' require 'pipeline/game/mapiplfile' require 'pipeline/os/path' require 'pipeline/log/log' require 'pipeline/util/rage' #----------------------------------------------------------------------------- # Code #----------------------------------------------------------------------------- module Pipeline module Game # # == Description # This class is a helper class to load a Rockstar North game's data files # into memory for further processing. # # E.g. it can be used to load all map IDE/IPL files for later processing # by data exporters or statistics tools. # class GameDataLoader class Error < StandardError; end attr_reader :project # Associated project attr_reader :project_ides # Hash ide_filename => IDEFile attr_reader :project_ipls # Hash ipl_filename => IPLFile attr_reader :project_imgs # Hash img_filename => IMGFile #--------------------------------------------------------------------- # Virtual Attributes #--------------------------------------------------------------------- def total_definitions total = 0 @project_ides.each do |ide_filename, ideobj| total += ideobj.total_definitions end total end #--------------------------------------------------------------------- # Constructor #--------------------------------------------------------------------- # # Constructor, loads all game definition and placement data using the # project configuration, based on the game_tag specified. # def initialize( project ) @log = Log.new( 'Game Data Loader' ) @project = project @r = Pipeline::RageUtils.instance() @project_ides = {} @project_ipls = {} @project_imgs = {} @definitions_cache = {} # Ensure project and RAGE are properly initialised... @project.load_config() @project.load_content() end #--------------------------------------------------------------------- # Public Methods #--------------------------------------------------------------------- # # Load all project IDE files based on nodes in the project's content # tree. # def load_ides( verbose = false ) puts "Loading Project #{@project.uiname} IDE Files..." content = @project.content.find_first_group( 'output_inner' ) @project.in_env do |env| content.walk do |c| next unless ( c.is_a?( Pipeline::Content::MapImage ) ) c.inputs.each do |input| next unless ( input.is_a?( Pipeline::Content::Map ) ) next unless ( input.exportdefinitions ) ide_filename = env.subst( OS::Path.combine( c.path, input.name ) + '.ide' ) next unless ::File::exists?( ide_filename ) load_ide_file( ide_filename, verbose ) end end end end # # Load all project IPL files based on nodes in the project's content # tree. # def load_ipls( verbose = false ) puts "Loading Project #{@project.uiname} IPL Files..." content = @project.content.find_first_group( 'output_inner' ) @project.in_env do |env| content.walk do |c| next unless ( c.is_a?( Pipeline::Content::MapImage ) ) c.inputs.each do |input| next unless ( input.is_a?( Pipeline::Content::Map ) ) next unless ( input.exportinstances ) ipl_filename = env.subst( OS::Path.combine( c.path, input.name ) + '.ipl' ) img_filename = env.subst( OS::Path.combine( c.path, input.name ) + '.img' ) next unless ::File::exists?( ipl_filename ) load_ipl_file( ipl_filename, img_filename, verbose ) end end end end # # == Description # Return an IDEDef object for the specified instance object. Return nil # if not found, or not loaded. # def find_def_for_inst( instance ) throw ArgumentError.new( "Specify IPLObjInst object" ) \ unless ( instance.is_a?( IPLObjInst ) ) return @definitions_cache[instance.name] if ( @definitions_cache.has_key?( instance.name ) ) nil end #--------------------------------------------------------------------- # Private Attributes #--------------------------------------------------------------------- private attr_reader :definition_cache #--------------------------------------------------------------------- # Private Constants #--------------------------------------------------------------------- private IMAGE_MOUNT = 'image:/' #--------------------------------------------------------------------- # Private Methods #--------------------------------------------------------------------- private # # Load a single IDE file # def load_ide_file( map_ide_path, verbose = false ) raise ArgumentError.new( "IDE File #{map_ide_path} does not exist." ) \ unless File.exists?( map_ide_path ) puts "Loading IDE: #{map_ide_path}" if verbose idefile = MapIDEFile.new( map_ide_path ) @project_ides[map_ide_path] = idefile # Populate our definition cache for easy lookup later. This # could be built on first access to find_def_for_inst() # function. addToDefCache( idefile ) end # # Load IPL file(s) for a specific map section. # def load_ipl_file( map_ipl_path, map_img_path, verbose = false ) raise ArgumentError.new( "IPL file #{map_ipl_path} does not exist." ) \ unless File.exists?( map_ipl_path ) raise ArgumentError.new( "IMG file #{map_img_path} does not exist." ) \ unless File.exists?( map_img_path ) puts "Loading IPL: #{map_ipl_path}" if verbose @project_ipls[map_ipl_path] = MapIPLFile.new( map_ipl_path ) # Load all map image IPLs... @r.image.mount( map_img_path, IMAGE_MOUNT ) found_files = @r.find_files( "#{IMAGE_MOUNT}*.ipl" ) found_files.each do |file| if ( @project_ipls.has_key?( "#{IMAGE_MOUNT}#{file}" ) ) @log.warn( "GameDataLoader: IPL File #{file} already loaded." ) next end puts "\tLoading sub-IPL: #{IMAGE_MOUNT}#{file}" if verbose @project_ipls[file] = MapIPLFile.new( "#{IMAGE_MOUNT}#{file}" ) end end # # # def addToDefCache( idefile ) raise "idefile not MapIDEFile class." unless MapIDEFile == idefile.class idefile.object_definitions.each do |obj| @definitions_cache[obj.name.downcase] = obj end idefile.time_object_definitions.each do |obj| @definitions_cache[obj.name.downcase] = obj end end end end # Game module end # Pipeline module # End of gamedataloader.rb