Files
2025-09-29 00:52:08 +02:00

133 lines
3.9 KiB
Ruby
Executable File

#
# File:: levels.rb
# Description:: Levels.xml and <level>.dat file parser.
#
# Author:: David Muir <david.muir@rockstarnorth.com>
# Date:: 26 November 2008
#
#----------------------------------------------------------------------------
# Uses
#----------------------------------------------------------------------------
require 'pipeline/os/path'
require 'pipeline/util/string'
require 'rexml/document'
#----------------------------------------------------------------------------
# Implementation
#----------------------------------------------------------------------------
module Pipeline
#
# == Description
# The Pipeline::Levels class defines a levels.xml parser and <level>.dat file
# parser for fetching information about a level. The concept of levels was
# first introduced in Jimmy.
#
class Levels
attr_reader :project # Project reference
attr_reader :branch # Branch reference
attr_reader :filename # String filename of levels.xml file.
attr_reader :levels # Hash of level uiname to Level objects.
def initialize( project, branch, filename )
throw ArgumentError.new( "Invalid project object (#{project.class})." ) \
unless ( project.is_a?( Pipeline::Project ) )
throw ArgumentError.new( "Invalid branch object (#{branch.class})." ) \
unless ( branch.is_a?( Pipeline::Branch ) )
project.load_config( )
@project = project
@branch = branch
@filename = filename
@levels = {}
File.open( @filename ) do |fp|
xmldoc = REXML::Document.new( fp )
xmldoc.elements.each( 'levels/level' ) do |xml_node|
level = Level::from_xml( xml_node, self )
throw RuntimeError.new( "Duplicate level data, key #{level.uiname} already used." ) \
if ( @levels.has_key?( level.uiname ) )
@levels[level.uiname] = level
end
end
end
end
#
# == Description
# The Pipeline::Level class defines data read from the levels.xml file and
# the <level>.dat file - essentially a mapping of file type to a filename.
#
# The filenames returned have environment values ready for substitution.
#
class Level
attr_reader :levels # Reference to owning Levels object.
attr_reader :uiname # Level friendlyname
attr_reader :title # Level title string
attr_reader :dat_filename # String filename of <level>.dat file.
attr_reader :dat # Hash of file type String keys to filenames
def initialize( levels, uiname, title, dat_filename )
@levels = levels
@uiname = uiname
@title = title
@levels.branch.in_env do |env|
@dat_filename = env.subst( dat_filename )
end
@dat = {}
parse_dat( )
end
#
# Create a Level object from an XML node.
#
def Level::from_xml( xml_node, levels )
uiname = xml_node.attributes['friendlyName']
title = xml_node.attributes['title']
filename = xml_node.attributes['filename']
filename.gsub!( 'common:', '$(common)' )
Level.new( levels, uiname, title, filename )
end
#--------------------------------------------------------------------------
# Private Methods
#--------------------------------------------------------------------------
private
def parse_dat( )
dat_data = []
File::open( @dat_filename ) do |fp|
dat_data = fp.readlines( )
end
dat_data.each do |line|
# Ignore comments and empty lines
line.strip!
next if ( 0 == line.size )
next if ( line.starts_with( '#' ) )
# Replace common: and platform: with our environment tokens.
line_dup = line.dup
line_dup.gsub!( /common:/i, '$(common)' )
line_dup.gsub!( /platform:/i, '$(platform)' )
@levels.branch.in_env do |env|
parts = line_dup.split( ' ' )
key = parts[0].upcase
file = env.subst( OS::Path::normalise( parts[1] ) )
@dat[key] = [] unless ( @dat.has_key?( key ) )
@dat[key] << file
end
end
end
end
end
# levels.rb