A Field wraps a GFF label->value pair, providing:
- .field_type describing the field type (e.g. :int)
- .field_value holding the value of this Field
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']
Methods
public class
public instance
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
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
Deep-unboxes a Hash, e.g. iterating down, converting all strings from the native charset.
# 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
Validate if value is within bounds of type.
# 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
Returns a hash of this Field without the API calls mixed in, all language-strings transformed by str_handler.
# 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
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) ? 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
# File lib/nwn/gff/field.rb, line 82 def field_label= l self['label']= l end
# File lib/nwn/gff/field.rb, line 59 def field_type= t self['type'] = t end
# 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
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
# File lib/nwn/json_support.rb, line 10 def to_json(*a) box.to_json(*a) end
Validate if this field value is within the bounds of the set type.
# File lib/nwn/gff/field.rb, line 119 def valid? NWN::Gff::Field.valid_for? self.v, self.t end
Validate this field, and raise an Excpetion if not valid.
# 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