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 46: def self.new label, type, value 47: s = {}.extend(self) 48: s['label'], s['type'], s['value'] = label, type.to_sym, value 49: s.extend_meta_classes 50: s.validate 51: s 52: end
Deep-unboxes a Hash, e.g. iterating down, converting all strings from the native charset.
# File lib/nwn/gff/field.rb, line 221 221: def self.unbox! element, parent_label, parent 222: element.extend(NWN::Gff::Field) 223: element.field_label = parent_label 224: element.parent = parent 225: element.str_ref ||= NWN::Gff::Field::DEFAULT_STR_REF if element.respond_to?('str_ref=') 226: 227: element.extend_meta_classes 228: case element.field_type 229: when :cexolocstr 230: element.field_value.each {|x,y| 231: element.field_value[x.to_i] = NWN.iconv_native_to_gff(element.field_value.delete(x)) 232: } 233: when :cexostr 234: element.field_value = NWN.iconv_native_to_gff(element.field_value) 235: 236: when :list 237: element.field_value.each_with_index {|x,idx| 238: element.field_value[idx] = NWN::Gff::Struct.unbox!(x, element) 239: } 240: when :struct 241: element.field_value = NWN::Gff::Struct.unbox!(element.field_value, element) 242: end 243: element.validate 244: element 245: end
Validate if value is within bounds of type.
# File lib/nwn/gff/field.rb, line 131 131: def self.valid_for? value, type 132: case type 133: when :byte, :char 134: value.is_a?(Integer) && value >= 0 && value <= 255 135: 136: when :short 137: value.is_a?(Integer) && value >= -0x8000 && value <= 0x7fff 138: when :word 139: value.is_a?(Integer) && value >= 0 && value <= 0xffff 140: 141: when :int 142: value.is_a?(Integer) && value >= -0x80000000 && value <= 0x7fffffff 143: when :dword 144: value.is_a?(Integer) && value >= 0 && value <= 0xffffffff 145: 146: when :int64 147: value.is_a?(Integer) && value >= -0x8000000000000000 && value <= 0x7fffffffffffffff 148: when :dword64 149: value.is_a?(Integer) && value >= 0 && value <= 0xffffffffffffffff 150: 151: when :float, :double 152: value.is_a?(Float) 153: 154: when :resref 155: if !NWN.setting(:resref32) && value.is_a?(String) && value.size > 16 156: NWN.log_debug("Warning: :resref too long for NWN1, set env NWN_LIB_RESREF32=1 to turn off warning for NWN2.") 157: NWN.log_debug(" Value found: #{value.inspect}") 158: end 159: 160: if NWN.setting(:resref16) 161: value.is_a?(String) && (0..16).member?(value.size) 162: else 163: value.is_a?(String) && (0..32).member?(value.size) 164: end 165: 166: when :cexostr 167: value.is_a?(String) 168: 169: when :cexolocstr 170: value.is_a?(Hash) && 171: value.keys.reject {|x| x.is_a?(Fixnum) && x >= 0 }.size == 0 && 172: value.values.reject {|x| x.is_a?(String) }.size == 0 173: 174: when :struct 175: value.is_a?(Hash) 176: 177: when :list 178: value.is_a?(Array) 179: 180: when :void 181: value.is_a?(String) 182: 183: else 184: false 185: end 186: 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 249: def box 250: t = Hash[self] 251: t.delete('label') 252: case field_type 253: when :cexolocstr 254: t['value'].each {|x,y| 255: t['value'][x] = NWN.iconv_gff_to_native(y) 256: } 257: when :cexostr 258: t['value'] = NWN.iconv_gff_to_native(t['value']) 259: end 260: t 261: 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 102: def extend_meta_classes 103: return if field_type == :struct 104: 105: field_klass_name = field_type.to_s.capitalize 106: field_klass = NWN::Gff.const_defined?(field_klass_name) ? 107: NWN::Gff.const_get(field_klass_name) : nil 108: field_value_klass = NWN::Gff.const_defined?(field_klass_name + 'Value') ? 109: NWN::Gff.const_get(field_klass_name + 'Value') : nil 110: 111: self.extend(field_klass) unless field_klass.nil? || 112: self.is_a?(field_klass) 113: 114: field_value.extend(field_value_klass) unless field_value_klass.nil? || 115: field_value.is_a?(field_value_klass) 116: end
# File lib/nwn/gff/field.rb, line 77 77: def field_label 78: self['label'] 79: end
# File lib/nwn/gff/field.rb, line 82 82: def field_label= l 83: self['label']= l 84: end
# File lib/nwn/gff/field.rb, line 54 54: def field_type 55: self['type'] 56: end
# File lib/nwn/gff/field.rb, line 59 59: def field_type= t 60: self['type'] = t 61: end
# File lib/nwn/gff/field.rb, line 64 64: def field_value 65: self['value'] 66: end
# File lib/nwn/gff/field.rb, line 69 69: def field_value= v 70: NWN::Gff::Field.valid_for?(v, field_type) or raise ArgumentError, 71: "Given field_value is not valid for type #{field_type.inspect}." 72: 73: self['value'] = v 74: end
# File lib/nwn/gff/cexolocstr.rb, line 2 2: def has_str_ref? 3: false 4: end
Returns the path to this field, including all parents structs. For example: UTI/PropertiesList/CostTable
# File lib/nwn/gff/field.rb, line 89 89: def path 90: raise NWN::Gff::GffError, "field not bound to a parent" unless @parent 91: parent_path = @parent.path 92: if @parent.element && @parent.element.field_type == :list 93: idx = @parent.element.field_value.index(@parent) 94: parent_path + "[#{idx}]/" + field_label 95: else 96: parent_path + "/" + field_label 97: end.gsub(%r{/+}, "/") 98: end
# File lib/nwn/json_support.rb, line 10 10: def to_json(*a) 11: box.to_json(*a) 12: end
Validate if this field value is within the bounds of the set type.
# File lib/nwn/gff/field.rb, line 119 119: def valid? 120: NWN::Gff::Field.valid_for? self.v, self.t 121: end
Validate this field, and raise an Excpetion if not valid.
# File lib/nwn/gff/field.rb, line 124 124: def validate 125: valid? or raise NWN::Gff::GffError, 126: "#{self.path rescue $!.to_s + '/' + self.l}: " + 127: "value '#{self.v.inspect}' not valid for type '#{self.t.inspect}'" 128: end