module NWN::Gff::Field

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

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

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

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) click to toggle source

Create a new NWN::Gff::Field

# 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
valid_for?(value, type) click to toggle source

Validate if value is within bounds of type.

# File lib/nwn/gff/field.rb, line 132
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) || value.is_a?(Integer)

    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?(Integer) && 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

encode_with(out) click to toggle source
# File lib/nwn/yaml_support.rb, line 45
def encode_with out
  out.map do |map|
    map.tag = nil
    map.style = Psych::Nodes::Mapping::FLOW unless
      NWN::Gff::Handler::YAML::NonInlineableFields.index(self['type'])
    map.add('type', self['type'].to_s)
    map.add('str_ref', self['str_ref']) if has_str_ref?
    map.add('value', self['value'])
  end
end
extend_meta_classes() click to toggle source

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

# 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, false) ?
    NWN::Gff.const_get(field_klass_name, false) : nil
  field_value_klass = NWN::Gff.const_defined?(field_klass_name + 'Value', false) ?
    NWN::Gff.const_get(field_klass_name + 'Value', false) : 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() click to toggle source
# File lib/nwn/gff/field.rb, line 77
def field_label
  self['label']
end
Also aliased as: l
field_label=(l) click to toggle source
# File lib/nwn/gff/field.rb, line 82
def field_label= l
  self['label']= l
end
Also aliased as: l=
field_type() click to toggle source
# File lib/nwn/gff/field.rb, line 54
def field_type
  self['type']
end
Also aliased as: t
field_type=(t) click to toggle source
# File lib/nwn/gff/field.rb, line 59
def field_type= t
  self['type'] = t
end
Also aliased as: t=
field_value() click to toggle source
# File lib/nwn/gff/field.rb, line 64
def field_value
  self['value']
end
Also aliased as: v
field_value=(v) click to toggle 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
Also aliased as: v=
has_str_ref?() click to toggle 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() click to toggle source

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

# 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) click to toggle source
# File lib/nwn/json_support.rb, line 38
def to_json(*a)
  json_box.to_json(*a)
end
v()
Alias for: field_value
v=(v)
Alias for: field_value=
valid?() click to toggle source

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

# File lib/nwn/gff/field.rb, line 120
def valid?
  NWN::Gff::Field.valid_for? self.v, self.t
end
validate() click to toggle source

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

# File lib/nwn/gff/field.rb, line 125
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

Private Instance Methods

json_box() click to toggle source
# File lib/nwn/json_support.rb, line 27
def json_box
  t = Hash[self]
  t.delete('label')
  case field_type
    when :void
      t['value'] = Base64::strict_encode64(t['value'])
  end
  t
end