Module NWN::Gff::Field

  1. lib/nwn/gff/cexolocstr.rb
  2. lib/nwn/gff/field.rb
  3. lib/nwn/json_support.rb
  4. show all

A Field wraps a GFF label->value pair, providing:

and, if loaded by Gff::Reader or through YAML:

  • .field_label holding the label
  • .parent holding the struct this Field is child of.

Note that it is ADVISED to use the provided accessors, since they do some structure-keeping in the background. If you do NOT want it to do that, use hash-notation for access:

field['value'], field['type'], field['str_ref'], field['label']

Constants

DEFAULT_VALUES = { :byte => 0, :char => 0, :word => 0, :short => 0, :dword => 0, :int => 0, :dword64 => 0, :int64 => 0, :float => 0.0, :double => 0.0, :cexostr => '', :resref => '', :cexolocstr => {}.extend(NWN::Gff::CexolocstrValue), :void => '', :struct => NWN::Gff::Struct.new, :list => [], }   The default values of fields.

Attributes

parent [RW] The parent struct. This is set internally by Gff::Reader on load.

Public class methods

new (label, type, value)

Create a new NWN::Gff::Field

[show source]
# File lib/nwn/gff/field.rb, line 46
  def self.new label, type, value
    s = {}.extend(self)
    s['label'], s['type'], s['value'] = label, type.to_sym, value
    s.extend_meta_classes
    s.validate
    s
  end
unbox! (element, parent_label, parent)

Deep-unboxes a Hash, e.g. iterating down, converting all strings from the native charset.

[show source]
# File lib/nwn/gff/field.rb, line 221
  def self.unbox! element, parent_label, parent
    element.extend(NWN::Gff::Field)
    element.field_label = parent_label
    element.parent = parent
    element.str_ref ||= NWN::Gff::Field::DEFAULT_STR_REF if element.respond_to?('str_ref=')

    element.extend_meta_classes
    case element.field_type
      when :cexolocstr
        element.field_value.each {|x,y|
          element.field_value[x.to_i] = NWN.iconv_native_to_gff(element.field_value.delete(x))
        }
      when :cexostr
        element.field_value = NWN.iconv_native_to_gff(element.field_value)

      when :list
        element.field_value.each_with_index {|x,idx|
          element.field_value[idx] = NWN::Gff::Struct.unbox!(x, element)
        }
      when :struct
        element.field_value = NWN::Gff::Struct.unbox!(element.field_value, element)
    end
    element.validate
    element
  end
valid_for? (value, type)

Validate if value is within bounds of type.

[show source]
# File lib/nwn/gff/field.rb, line 131
  def self.valid_for? value, type
    case type
      when :byte, :char
        value.is_a?(Integer) && value >= 0 && value <= 255

      when :short
        value.is_a?(Integer) && value >= -0x8000 && value <= 0x7fff
      when :word
        value.is_a?(Integer) && value >= 0 && value <= 0xffff

      when :int
        value.is_a?(Integer) && value >= -0x80000000 && value <= 0x7fffffff
      when :dword
        value.is_a?(Integer) && value >= 0 && value <= 0xffffffff

      when :int64
        value.is_a?(Integer) && value >= -0x8000000000000000 && value <= 0x7fffffffffffffff
      when :dword64
        value.is_a?(Integer) && value >= 0 && value <= 0xffffffffffffffff

      when :float, :double
        value.is_a?(Float)

      when :resref
        if !NWN.setting(:resref32) && value.is_a?(String) && value.size > 16
          NWN.log_debug("Warning: :resref too long for NWN1, set env NWN_LIB_RESREF32=1 to turn off warning for NWN2.")
          NWN.log_debug("  Value found: #{value.inspect}")
        end

        if NWN.setting(:resref16)
          value.is_a?(String) && (0..16).member?(value.size)
        else
          value.is_a?(String) && (0..32).member?(value.size)
        end

      when :cexostr
        value.is_a?(String)

      when :cexolocstr
        value.is_a?(Hash) &&
          value.keys.reject {|x| x.is_a?(Fixnum) && x >= 0 }.size == 0 &&
          value.values.reject {|x| x.is_a?(String) }.size == 0

      when :struct
        value.is_a?(Hash)

      when :list
        value.is_a?(Array)

      when :void
        value.is_a?(String)

      else
        false
    end
  end

Public instance methods

box ()

Returns a hash of this Field without the API calls mixed in, all language-strings transformed by str_handler.

[show source]
# File lib/nwn/gff/field.rb, line 249
  def box
    t = Hash[self]
    t.delete('label')
    case field_type
      when :cexolocstr
        t['value'].each {|x,y|
          t['value'][x] = NWN.iconv_gff_to_native(y)
        }
      when :cexostr
        t['value'] = NWN.iconv_gff_to_native(t['value'])
    end
    t
  end
extend_meta_classes ()

This extends this field object and its’ value with the appropriate meta classes, depending on field_type.

[show source]
# File lib/nwn/gff/field.rb, line 102
  def extend_meta_classes
    return if field_type == :struct

    field_klass_name = field_type.to_s.capitalize
    field_klass = NWN::Gff.const_defined?(field_klass_name) ?
      NWN::Gff.const_get(field_klass_name) : nil
    field_value_klass = NWN::Gff.const_defined?(field_klass_name + 'Value') ?
      NWN::Gff.const_get(field_klass_name + 'Value') : nil

    self.extend(field_klass) unless field_klass.nil? ||
      self.is_a?(field_klass)

    field_value.extend(field_value_klass) unless field_value_klass.nil? ||
      field_value.is_a?(field_value_klass)
  end
field_label ()
[show source]
# File lib/nwn/gff/field.rb, line 77
  def field_label
    self['label']
  end
field_label= (l)
[show source]
# File lib/nwn/gff/field.rb, line 82
  def field_label= l
    self['label']= l
  end
field_type ()
[show source]
# File lib/nwn/gff/field.rb, line 54
  def field_type
    self['type']
  end
field_type= (t)
[show source]
# File lib/nwn/gff/field.rb, line 59
  def field_type= t
    self['type'] = t
  end
field_value ()
[show source]
# File lib/nwn/gff/field.rb, line 64
  def field_value
    self['value']
  end
field_value= (v)
[show source]
# File lib/nwn/gff/field.rb, line 69
  def field_value= v
    NWN::Gff::Field.valid_for?(v, field_type) or raise ArgumentError,
      "Given field_value is not valid for type #{field_type.inspect}."

    self['value'] = v
  end
has_str_ref? ()
[show source]
# File lib/nwn/gff/cexolocstr.rb, line 2
  def has_str_ref?
    false
  end
l ()

Alias for field_label

l= (l)

Alias for field_label=

path ()

Returns the path to this field, including all parents structs. For example: UTI/PropertiesList/CostTable

[show source]
# File lib/nwn/gff/field.rb, line 89
  def path
    raise NWN::Gff::GffError, "field not bound to a parent" unless @parent
    parent_path = @parent.path
    if @parent.element && @parent.element.field_type == :list
      idx = @parent.element.field_value.index(@parent)
      parent_path + "[#{idx}]/" + field_label
    else
      parent_path + "/" + field_label
    end.gsub(%r{/+}, "/")
  end
t ()

Alias for field_type

t= (t)

Alias for field_type=

to_json (*a)
[show source]
# File lib/nwn/json_support.rb, line 10
  def to_json(*a)
    box.to_json(*a)
  end
v ()

Alias for field_value

v= (v)

Alias for field_value=

valid? ()

Validate if this field value is within the bounds of the set type.

[show source]
# File lib/nwn/gff/field.rb, line 119
  def valid?
    NWN::Gff::Field.valid_for? self.v, self.t
  end
validate ()

Validate this field, and raise an Excpetion if not valid.

[show source]
# File lib/nwn/gff/field.rb, line 124
  def validate
    valid? or raise NWN::Gff::GffError,
      "#{self.path rescue $!.to_s + '/' + self.l}: " +
        "value '#{self.v.inspect}' not valid for type '#{self.t.inspect}'"
  end