nwn-lib 0.4.8 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +18 -0
- data/COPYING +1 -1
- data/HOWTO +170 -0
- data/README +1 -1
- data/Rakefile +2 -2
- data/bin/nwn-erf +1 -1
- data/bin/nwn-irb +1 -1
- data/lib/nwn/gff.rb +0 -1
- data/lib/nwn/gff/field.rb +32 -0
- data/lib/nwn/gff/reader.rb +5 -7
- data/lib/nwn/gff/struct.rb +96 -0
- data/lib/nwn/scripting.rb +10 -3
- data/lib/nwn/twoda.rb +2 -2
- data/lib/nwn/yaml.rb +2 -2
- metadata +27 -26
- data/lib/nwn/gff/api.rb +0 -88
data/CHANGELOG
CHANGED
@@ -251,3 +251,21 @@ Bernhard Stoeckner <elven@swordcoast.net> (6):
|
|
251
251
|
|
252
252
|
Another bugfix and compatibility release. This adds real NWN2 support
|
253
253
|
to gff reading, adds a few new SETTINGS, and adds proper IO reading.
|
254
|
+
|
255
|
+
=== 0.4.9
|
256
|
+
Bernhard Stoeckner <elven@swordcoast.net> (10):
|
257
|
+
Gff::Reader/YAML: do not taint read objects
|
258
|
+
Scripting: satisfy win32 compatibility
|
259
|
+
nwn-irb: work on IO object instead of string
|
260
|
+
nwn-erf: fix typo in -h: -1 saying ERF 1.0 instead of ERF 1.1
|
261
|
+
Scripting: satisfy: close opened fds after loading GFF data
|
262
|
+
api.rb: merge into field.rb and struct.rb
|
263
|
+
Gff::Struct#by_path: print list index in current_path on error
|
264
|
+
Gff::Struct#by_path: / alias, $ and % mods, substruct & locname paths
|
265
|
+
TwoDA::Table: fix always printing errors for invalid IDs on table reading
|
266
|
+
Update documentation, add HOWTO
|
267
|
+
0.4.9-rel
|
268
|
+
|
269
|
+
Some medium rare bugfixes, and a overloaded operator for GFF structs,
|
270
|
+
which can be used to comfortable walk on trees.
|
271
|
+
|
data/COPYING
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (C) 2008 Bernhard Stoeckner <elven@swordcoast.net> and contributors
|
1
|
+
Copyright (C) 2008-current Bernhard Stoeckner <elven@swordcoast.net> and contributors
|
2
2
|
|
3
3
|
This program is free software; you can redistribute it and/or modify
|
4
4
|
it under the terms of the GNU General Public License as published by
|
data/HOWTO
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
=== Writing scripts to do the work for you
|
2
|
+
|
3
|
+
First, read SCRIPTING. Since an example is more worth than a thousand words,
|
4
|
+
here is a quick introduction in the form of a script that handles input
|
5
|
+
files from ARGV, does nothing with them, and then saves them back to the same
|
6
|
+
file from which they came from.
|
7
|
+
|
8
|
+
#!/usr/bin/env nwn-dsl
|
9
|
+
|
10
|
+
ARGV.each_with_index {|file, index|
|
11
|
+
# The script will abort hard if file is not an ARE.
|
12
|
+
# This looks up the data_type, which are usually the
|
13
|
+
# first four bytes of a file.
|
14
|
+
gff = need file, :are
|
15
|
+
|
16
|
+
# This will save gff back to 'file'.
|
17
|
+
save gff
|
18
|
+
|
19
|
+
# This will prefix all lines printed with log with
|
20
|
+
# a percentage. It's usage is optional, and the sole
|
21
|
+
# reason for using each_with_index instead of each above.
|
22
|
+
progress index
|
23
|
+
}
|
24
|
+
|
25
|
+
To run this example, type the following in a directory containing some .are
|
26
|
+
files, with script.rb being the name you saved the above script in.
|
27
|
+
|
28
|
+
nwn-dsl path/to/script.rb *.are
|
29
|
+
|
30
|
+
The shebang (#!/..) is for unixoid systems and Cygwin, and as such optional.
|
31
|
+
|
32
|
+
For all available commands to nwn-dsl scripts, see NWN::Gff::Scripting.
|
33
|
+
|
34
|
+
<b>All code snippets shown here assume that you put <tt>include NWN</tt>
|
35
|
+
in your application. It is not needed for nwn-dsl, which imports that
|
36
|
+
namespace for you.</b>
|
37
|
+
|
38
|
+
=== Accessing GFF paths
|
39
|
+
|
40
|
+
You can access GFF paths within structs by using the overloaded division
|
41
|
+
operator.
|
42
|
+
|
43
|
+
#!/usr/bin/env nwn-dsl
|
44
|
+
|
45
|
+
ARGV.each_with_index {|file, index|
|
46
|
+
gff = need file, :are
|
47
|
+
|
48
|
+
log (gff / 'Name/0')
|
49
|
+
|
50
|
+
progress index
|
51
|
+
}
|
52
|
+
|
53
|
+
For a full reference of the path syntax, see NWN::Gff::Struct#by_path.
|
54
|
+
|
55
|
+
You cannot use paths to assign new values to structs - you can only
|
56
|
+
modify existing values:
|
57
|
+
|
58
|
+
(gff / 'Name').v[0] = "New Localized Name with Language ID 0"
|
59
|
+
|
60
|
+
Wrong, will raise error:
|
61
|
+
|
62
|
+
(gff / 'Name/0') = "New .."
|
63
|
+
|
64
|
+
Please note that using the [] method will NOT evaluate paths, just
|
65
|
+
access labels in the CURRENT struct (which is actually a hash).
|
66
|
+
|
67
|
+
=== Creating new GFF Structs and Elements
|
68
|
+
|
69
|
+
You can add new fields to existing structs via NWN::Gff::Struct#add_field:
|
70
|
+
|
71
|
+
gff.add_field 'LocalVersion', :int, 1
|
72
|
+
|
73
|
+
# This will print "1"
|
74
|
+
log (gff / 'LocalVersion$')
|
75
|
+
|
76
|
+
You can also the dynamic methods to save some typing:
|
77
|
+
|
78
|
+
gff.add_int 'LocalVersion', 1
|
79
|
+
|
80
|
+
You can just as well create whole GFF structures on the fly:
|
81
|
+
|
82
|
+
Gff::Struct.new do |s|
|
83
|
+
s.add_byte 'ImaByte', :int, 1
|
84
|
+
list = s.add_list 'ImaList', [] do |l|
|
85
|
+
l.add_struct(1) do |ss|
|
86
|
+
ss.add_byte 'ImaByteToo', 2
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
Further reading: NWN::Gff::Struct#add_field, NWN::Gff::List#add_struct.
|
92
|
+
|
93
|
+
=== Working with .2da files
|
94
|
+
|
95
|
+
Working with TwoDA files is easy and painless:
|
96
|
+
|
97
|
+
#!/usr/bin/env nwn-dsl
|
98
|
+
|
99
|
+
data = IO.read('path/to/baseitems.2da')
|
100
|
+
table = TwoDA::Table.parse(data)
|
101
|
+
|
102
|
+
# This will print "twobladedsword" with NWN1 1.69
|
103
|
+
log table[12].Label
|
104
|
+
|
105
|
+
# You can re-format (and save) any valid table:
|
106
|
+
File.open("/tmp/out", "wb") {|f|
|
107
|
+
f.write(table.to_2da)
|
108
|
+
# OR
|
109
|
+
table.write_to(f)
|
110
|
+
}
|
111
|
+
|
112
|
+
For more documentation, see NWN::TwoDA::Table and
|
113
|
+
NWN::TwoDA::Row.
|
114
|
+
|
115
|
+
You can also set up a default location for 2da files,
|
116
|
+
after which you can simply use the following to read
|
117
|
+
2da files:
|
118
|
+
|
119
|
+
table = TwoDA.get('baseitems')
|
120
|
+
|
121
|
+
You can set up the TwoDA::Cache by either setting the
|
122
|
+
environment variable (recommended, see SETTINGS), or
|
123
|
+
like this (see NWN::TwoDA::Cache.setup):
|
124
|
+
|
125
|
+
TwoDA::Cache.setup("path_a:path_b/blah:path_c")
|
126
|
+
|
127
|
+
=== Accessing .tlk data
|
128
|
+
|
129
|
+
You can access individual .tlk files, or use a TlkSet,
|
130
|
+
which will emulate the way NWN1/2 reads it's .tlk files.
|
131
|
+
|
132
|
+
Read a simple .tlk file:
|
133
|
+
|
134
|
+
io = File.open("/path/to/dialog.tlk", "rb")
|
135
|
+
tlk = NWN::Tlk::Tlk.new(io)
|
136
|
+
|
137
|
+
Note that Tlk::Tlk seeks and reads from +io+ as needed,
|
138
|
+
so if you close the file handle, any further accesses
|
139
|
+
will fail.
|
140
|
+
|
141
|
+
# Retrieve strref 12
|
142
|
+
tlk[12][:text]
|
143
|
+
|
144
|
+
# Retrieve the attached sound resref, if any:
|
145
|
+
tlk[12][:sound]
|
146
|
+
|
147
|
+
# prints the highest strref used
|
148
|
+
log tlk.highest_id
|
149
|
+
|
150
|
+
# Add a new strrref.
|
151
|
+
new_strref = tlk.add 'New text'
|
152
|
+
|
153
|
+
# And save the new TLK somewhere else.
|
154
|
+
File.open("/tmp/new.tlk", "wb") {|another_io|
|
155
|
+
tlk.write_to(another_io)
|
156
|
+
}
|
157
|
+
|
158
|
+
Now read-only access with a TlkSet:
|
159
|
+
|
160
|
+
# The arguments are dialog.tlk, dialogf.tlk,
|
161
|
+
# custom.tlk and a customf.tlk each wrapped in
|
162
|
+
# a Tlk::Tlk as shown above.
|
163
|
+
set = Tlk::TlkSet.new(tlk, tlkf, custom, customf)
|
164
|
+
|
165
|
+
# Retrieve str_ref 12 as the female variant (dialogf.tlk)
|
166
|
+
# if present, :male otherwise.
|
167
|
+
log set[12, :female]
|
168
|
+
|
169
|
+
You cannot use TlkSet to write out .tlk files or modify
|
170
|
+
existing entries - it is merely a wrapper.
|
data/README
CHANGED
data/Rakefile
CHANGED
@@ -9,13 +9,13 @@ include FileUtils
|
|
9
9
|
# Configuration
|
10
10
|
##############################################################################
|
11
11
|
NAME = "nwn-lib"
|
12
|
-
VERS = "0.4.
|
12
|
+
VERS = "0.4.9"
|
13
13
|
CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage"]
|
14
14
|
RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
|
15
15
|
'nwn-lib: a ruby library for accessing NWN resource files', \
|
16
16
|
'--main', 'README']
|
17
17
|
|
18
|
-
DOCS = ["README", "BINARIES", "SCRIPTING", "SETTINGS", "CHEATSHEET", "CHANGELOG", "COPYING"]
|
18
|
+
DOCS = ["README", "BINARIES", "HOWTO", "SCRIPTING", "SETTINGS", "CHEATSHEET", "CHANGELOG", "COPYING"]
|
19
19
|
|
20
20
|
Rake::RDocTask.new do |rdoc|
|
21
21
|
rdoc.rdoc_dir = "rdoc"
|
data/bin/nwn-erf
CHANGED
@@ -66,7 +66,7 @@ begin OptionParser.new do |o|
|
|
66
66
|
o.on "-0", "Create (only -c) V1.0 ERF, 16 byte resrefs. (NWN1, default)" do
|
67
67
|
$version = "V1.0"
|
68
68
|
end
|
69
|
-
o.on "-1", "Create (only -c) V1.
|
69
|
+
o.on "-1", "Create (only -c) V1.1 ERF, 32 byte resrefs. (NWN2)." do
|
70
70
|
$version = "V1.1"
|
71
71
|
end
|
72
72
|
|
data/bin/nwn-irb
CHANGED
@@ -29,7 +29,7 @@ def read file
|
|
29
29
|
file = File.expand_path(file || $file)
|
30
30
|
$stderr.puts "Reading `#{file}' .."
|
31
31
|
fmt = NWN::Gff.guess_file_format(file)
|
32
|
-
$gff = NWN::Gff.read(
|
32
|
+
$gff = NWN::Gff.read(File.open(file, "rb"), fmt)
|
33
33
|
|
34
34
|
$stderr.puts "Your GFF file is in `$gff' (data_type: #{$gff.data_type.inspect})."
|
35
35
|
$stderr.puts "Type `save' to save to the filename it came from (make a backup!), `exit' (or Ctrl+D) to exit (without saving)."
|
data/lib/nwn/gff.rb
CHANGED
data/lib/nwn/gff/field.rb
CHANGED
@@ -158,4 +158,36 @@ module NWN::Gff::Field
|
|
158
158
|
false
|
159
159
|
end
|
160
160
|
end
|
161
|
+
|
162
|
+
#:stopdoc:
|
163
|
+
# Used by NWN::Gff::Struct#by_flat_path
|
164
|
+
def each_by_flat_path &block
|
165
|
+
case field_type
|
166
|
+
when :cexolocstr
|
167
|
+
yield("", self)
|
168
|
+
field_value.sort.each {|lid, str|
|
169
|
+
yield("/" + lid.to_s, str)
|
170
|
+
}
|
171
|
+
|
172
|
+
when :struct
|
173
|
+
yield("", self)
|
174
|
+
field_value.each_by_flat_path {|v, x|
|
175
|
+
yield(v, x)
|
176
|
+
}
|
177
|
+
|
178
|
+
when :list
|
179
|
+
yield("", self)
|
180
|
+
field_value.each_with_index {|item, index|
|
181
|
+
yield("[" + index.to_s + "]", item)
|
182
|
+
item.each_by_flat_path("/") {|v, x|
|
183
|
+
yield("[" + index.to_s + "]" + v, x)
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
else
|
188
|
+
yield("", self)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
#:startdoc:
|
192
|
+
|
161
193
|
end
|
data/lib/nwn/gff/reader.rb
CHANGED
@@ -67,7 +67,7 @@ class NWN::Gff::Reader
|
|
67
67
|
|
68
68
|
# This iterates through a struct and reads all fields into a hash, which it returns.
|
69
69
|
def read_struct index, file_type = nil, file_version = nil
|
70
|
-
struct = {}
|
70
|
+
struct = {}
|
71
71
|
struct.extend(NWN::Gff::Struct)
|
72
72
|
|
73
73
|
type = @structs[index * 3]
|
@@ -101,9 +101,7 @@ class NWN::Gff::Reader
|
|
101
101
|
|
102
102
|
# Reads the field at +index+ and returns [label_name, Gff::Field]
|
103
103
|
def read_field index, parent_of
|
104
|
-
|
105
|
-
|
106
|
-
field = {}.taint
|
104
|
+
field = {}
|
107
105
|
field.extend(NWN::Gff::Field)
|
108
106
|
|
109
107
|
index *= 3
|
@@ -184,7 +182,7 @@ class NWN::Gff::Reader
|
|
184
182
|
len = total_size + 4
|
185
183
|
# Filter out empty strings.
|
186
184
|
exostr.reject! {|k,v| v.nil? || v.empty?}
|
187
|
-
exostr
|
185
|
+
exostr
|
188
186
|
|
189
187
|
when :void
|
190
188
|
len = @field_data[data_or_offset, 4].unpack("V")[0]
|
@@ -215,7 +213,7 @@ class NWN::Gff::Reader
|
|
215
213
|
list << read_struct(@list_indices[i], field.path, field.parent.data_version)
|
216
214
|
end
|
217
215
|
|
218
|
-
list
|
216
|
+
list
|
219
217
|
|
220
218
|
end
|
221
219
|
|
@@ -226,7 +224,7 @@ class NWN::Gff::Reader
|
|
226
224
|
[value].compact.flatten.each {|iv|
|
227
225
|
iv.element = field if iv.respond_to?('element=')
|
228
226
|
}
|
229
|
-
field['value'] = value
|
227
|
+
field['value'] = value
|
230
228
|
|
231
229
|
# We extend all fields and field_values with matching classes.
|
232
230
|
field.extend_meta_classes
|
data/lib/nwn/gff/struct.rb
CHANGED
@@ -104,4 +104,100 @@ module NWN::Gff::Struct
|
|
104
104
|
def to_s
|
105
105
|
"<NWN::Gff::Struct #{self.data_type}/#{self.data_version}, #{self.keys.size} fields>"
|
106
106
|
end
|
107
|
+
|
108
|
+
|
109
|
+
# Iterates this struct, yielding flat, absolute
|
110
|
+
# paths and the Gff::Field for each element found.
|
111
|
+
|
112
|
+
# Example:
|
113
|
+
# "/AddCost" => {"type"=>:dword, ..}
|
114
|
+
def each_by_flat_path prefix = "/", &block
|
115
|
+
sort.each {|label, field|
|
116
|
+
field.each_by_flat_path do |ll, lv|
|
117
|
+
yield(prefix + label + ll, lv)
|
118
|
+
end
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
# Retrieve an object from within the given tree.
|
123
|
+
# Path is a slash-separated destination, given as
|
124
|
+
# a string
|
125
|
+
#
|
126
|
+
# Prefixed/postfixed slashes are optional.
|
127
|
+
#
|
128
|
+
# You can retrieve CExoLocString values by giving the
|
129
|
+
# language ID as the last label:
|
130
|
+
# /FirstName/0
|
131
|
+
#
|
132
|
+
# You can retrieve list values by specifying the index
|
133
|
+
# in square brackets:
|
134
|
+
# /SkillList[0]
|
135
|
+
# /SkillList[0]/Rank => {"Rank"=>{"label"=>"Rank", "value"=>0, "type"=>:byte}}
|
136
|
+
#
|
137
|
+
# You can directly retrieve field values and types
|
138
|
+
# instead of the field itself:
|
139
|
+
# /SkillList[0]/Rank$ => 0
|
140
|
+
# /SkillList[0]/Rank? => :byte
|
141
|
+
#
|
142
|
+
# This will raise an error for non-field paths, naturally:
|
143
|
+
# SkillList[0]$ => undefined method `field_value' for {"Rank"=>{"label"=>"Rank", "value"=>0, "type"=>:byte}}:Hash
|
144
|
+
# SkillList[0]? => undefined method `field_type' for {"Rank"=>{"label"=>"Rank", "value"=>0, "type"=>:byte}}:Hash
|
145
|
+
#
|
146
|
+
# For CExoLocStrings, you can retrieve the str_ref:
|
147
|
+
# FirstName% => 4294967295
|
148
|
+
# This will return DEFAULT_STR_REF (0xffffffff) if the given path does not have
|
149
|
+
# a str_ref.
|
150
|
+
def by_path path
|
151
|
+
struct = self
|
152
|
+
current_path = ""
|
153
|
+
path = path.split('/').map {|v| v.strip }.reject {|v| v.empty?}.join('/')
|
154
|
+
|
155
|
+
path, mod = $1, $2 if path =~ /^(.+?)([\$\?%])?$/
|
156
|
+
|
157
|
+
path.split('/').each_with_index {|v, path_index|
|
158
|
+
if struct.is_a?(NWN::Gff::Field) && struct.field_type == :cexolocstr &&
|
159
|
+
v =~ /^\d+$/ && path_index == path.split('/').size - 1
|
160
|
+
struct = struct.field_value[v.to_i]
|
161
|
+
break
|
162
|
+
end
|
163
|
+
|
164
|
+
v, index = $1, $2 if v =~ /^(.+?)\[(\d+)\]$/
|
165
|
+
|
166
|
+
struct = struct.v if struct.is_a?(NWN::Gff::Field) &&
|
167
|
+
struct.field_type == :struct
|
168
|
+
|
169
|
+
struct = struct[v]
|
170
|
+
if index
|
171
|
+
struct.field_type == :list or raise NWN::Gff::GffPathInvalidError,
|
172
|
+
"Specified a list offset for a non-list item: #{v}[#{index}]."
|
173
|
+
|
174
|
+
struct = struct.field_value[index.to_i]
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
raise NWN::Gff::GffPathInvalidError,
|
179
|
+
"Cannot find a path to /#{path} (at: #{current_path})." unless struct
|
180
|
+
|
181
|
+
current_path += "/" + v
|
182
|
+
current_path += "[#{index}]" if index
|
183
|
+
}
|
184
|
+
|
185
|
+
case mod
|
186
|
+
when "$"
|
187
|
+
struct.field_value
|
188
|
+
when "?"
|
189
|
+
struct.field_type
|
190
|
+
when "%"
|
191
|
+
struct.has_str_ref? ? struct.str_ref :
|
192
|
+
NWN::Gff::Cexolocstr::DEFAULT_STR_REF
|
193
|
+
else
|
194
|
+
struct
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# An alias for +by_path+.
|
199
|
+
def / path
|
200
|
+
by_path(path)
|
201
|
+
end
|
202
|
+
|
107
203
|
end
|
data/lib/nwn/scripting.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Include this if you want to eval nwn-gff-dsl scripts.
|
4
4
|
module NWN::Gff::Scripting
|
5
5
|
|
6
|
-
class Sandbox
|
6
|
+
class Sandbox #:nodoc:
|
7
7
|
include NWN
|
8
8
|
include NWN::Gff::Scripting
|
9
9
|
end
|
@@ -99,11 +99,13 @@ module NWN::Gff::Scripting
|
|
99
99
|
# If only a filename/string is given and no further arguments,
|
100
100
|
# the read object will be returned as-is.
|
101
101
|
def satisfy *what
|
102
|
+
close_me = false
|
102
103
|
if $standalone
|
103
104
|
fn = what.shift
|
104
105
|
io = case fn
|
105
106
|
when String
|
106
|
-
|
107
|
+
close_me = true
|
108
|
+
File.new(fn, "rb")
|
107
109
|
when IO
|
108
110
|
fn
|
109
111
|
else
|
@@ -112,7 +114,12 @@ module NWN::Gff::Scripting
|
|
112
114
|
# "`need', `want' and `satisfy' need a filename or a IO " +
|
113
115
|
# "object to read from (usually the first script argument)."
|
114
116
|
end
|
115
|
-
|
117
|
+
|
118
|
+
obj = begin
|
119
|
+
NWN::Gff.read(io, NWN::Gff.guess_file_format(fn))
|
120
|
+
ensure
|
121
|
+
io.close if close_me
|
122
|
+
end
|
116
123
|
log "satisfied #{fn} -> #{obj.to_s}"
|
117
124
|
$satisfy_loaded[obj.object_id] = [fn, obj.hash]
|
118
125
|
|
data/lib/nwn/twoda.rb
CHANGED
@@ -132,7 +132,7 @@ module NWN
|
|
132
132
|
data.each_with_index {|row, idx|
|
133
133
|
id = row.shift
|
134
134
|
|
135
|
-
NWN.log_debug "Warning: invalid ID in line #{idx}: #{id.inspect}" if
|
135
|
+
NWN.log_debug "Warning: invalid ID in line #{idx}: #{id.inspect}" if id !~ /^\d+$/
|
136
136
|
|
137
137
|
id = id.to_i + id_offset
|
138
138
|
|
@@ -310,7 +310,7 @@ module NWN
|
|
310
310
|
|
311
311
|
# Set the file system path spec where all 2da files reside.
|
312
312
|
# Call this on application startup.
|
313
|
-
# path spec is a colon-separated list of
|
313
|
+
# path spec is a colon-separated list of paths, just like $PATH.
|
314
314
|
def self.setup root_directories
|
315
315
|
@_roots = root_directories.split(':').compact.reject {|x| "" == x.strip }
|
316
316
|
end
|
data/lib/nwn/yaml.rb
CHANGED
@@ -74,7 +74,7 @@ end
|
|
74
74
|
|
75
75
|
# This parses the struct and extends all fields with their proper type.
|
76
76
|
YAML.add_domain_type(NWN::YAML_DOMAIN,'struct') {|t,hash|
|
77
|
-
struct = {}
|
77
|
+
struct = {}
|
78
78
|
struct.extend(NWN::Gff::Struct)
|
79
79
|
|
80
80
|
# The metadata
|
@@ -96,7 +96,7 @@ YAML.add_domain_type(NWN::YAML_DOMAIN,'struct') {|t,hash|
|
|
96
96
|
element.extend_meta_classes
|
97
97
|
element.validate
|
98
98
|
|
99
|
-
struct[label] = element
|
99
|
+
struct[label] = element
|
100
100
|
}
|
101
101
|
|
102
102
|
struct
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nwn-lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernhard Stoeckner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-07-19 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -25,6 +25,7 @@ extensions: []
|
|
25
25
|
extra_rdoc_files:
|
26
26
|
- README
|
27
27
|
- BINARIES
|
28
|
+
- HOWTO
|
28
29
|
- SCRIPTING
|
29
30
|
- SETTINGS
|
30
31
|
- CHEATSHEET
|
@@ -35,51 +36,51 @@ files:
|
|
35
36
|
- CHANGELOG
|
36
37
|
- README
|
37
38
|
- Rakefile
|
38
|
-
- bin/nwn-gff
|
39
39
|
- bin/nwn-dsl
|
40
|
-
- bin/nwn-
|
40
|
+
- bin/nwn-gff
|
41
41
|
- bin/nwn-irb
|
42
|
-
-
|
42
|
+
- bin/nwn-erf
|
43
|
+
- spec/wellformed_gff.bic
|
43
44
|
- spec/gff_spec.rb
|
44
|
-
- spec/
|
45
|
-
- spec/
|
45
|
+
- spec/res_spec.rb
|
46
|
+
- spec/spec.opts
|
47
|
+
- spec/erf_spec.rb
|
46
48
|
- spec/field_spec.rb
|
47
49
|
- spec/cexolocstr_spec.rb
|
48
|
-
- spec/erf_spec.rb
|
49
50
|
- spec/struct_spec.rb
|
50
|
-
- spec/
|
51
|
-
- spec/res_spec.rb
|
51
|
+
- spec/spec_helper.rb
|
52
52
|
- spec/tlk_spec.rb
|
53
|
+
- spec/bin_dsl_spec.rb
|
54
|
+
- spec/bin_gff_spec.rb
|
53
55
|
- spec/rcov.opts
|
56
|
+
- spec/bin_erf_spec.rb
|
54
57
|
- spec/twoda_spec.rb
|
55
|
-
-
|
56
|
-
- spec/wellformed_gff.bic
|
57
|
-
- lib/nwn/erf.rb
|
58
|
-
- lib/nwn/io.rb
|
59
|
-
- lib/nwn/settings.rb
|
58
|
+
- lib/nwn/scripting.rb
|
60
59
|
- lib/nwn/yaml.rb
|
61
|
-
- lib/nwn/all.rb
|
62
|
-
- lib/nwn/res.rb
|
63
60
|
- lib/nwn/twoda.rb
|
64
|
-
- lib/nwn/
|
61
|
+
- lib/nwn/erf.rb
|
62
|
+
- lib/nwn/settings.rb
|
65
63
|
- lib/nwn/gff.rb
|
64
|
+
- lib/nwn/tlk.rb
|
65
|
+
- lib/nwn/io.rb
|
66
|
+
- lib/nwn/res.rb
|
66
67
|
- lib/nwn/kivinen.rb
|
67
|
-
- lib/nwn/
|
68
|
-
- lib/nwn/gff/
|
69
|
-
- lib/nwn/gff/writer.rb
|
70
|
-
- lib/nwn/gff/struct.rb
|
71
|
-
- lib/nwn/gff/list.rb
|
68
|
+
- lib/nwn/all.rb
|
69
|
+
- lib/nwn/gff/field.rb
|
72
70
|
- lib/nwn/gff/reader.rb
|
73
71
|
- lib/nwn/gff/cexolocstr.rb
|
74
|
-
- lib/nwn/gff/
|
72
|
+
- lib/nwn/gff/struct.rb
|
73
|
+
- lib/nwn/gff/list.rb
|
74
|
+
- lib/nwn/gff/writer.rb
|
75
75
|
- tools/verify.sh
|
76
76
|
- tools/migrate_03x_to_04x.sh
|
77
77
|
- scripts/truncate_floats.rb
|
78
|
+
- scripts/reformat_2da
|
78
79
|
- scripts/clean_locstrs.rb
|
79
|
-
- scripts/debug_check_objid.rb
|
80
80
|
- scripts/extract_all_items.rb
|
81
|
-
- scripts/
|
81
|
+
- scripts/debug_check_objid.rb
|
82
82
|
- BINARIES
|
83
|
+
- HOWTO
|
83
84
|
- SCRIPTING
|
84
85
|
- SETTINGS
|
85
86
|
- CHEATSHEET
|
data/lib/nwn/gff/api.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
|
2
|
-
module NWN::Gff::Field
|
3
|
-
#:stopdoc:
|
4
|
-
# Used by NWN::Gff::Struct#by_flat_path
|
5
|
-
def each_by_flat_path &block
|
6
|
-
case field_type
|
7
|
-
when :cexolocstr
|
8
|
-
yield("", self)
|
9
|
-
field_value.sort.each {|lid, str|
|
10
|
-
yield("/" + lid.to_s, str)
|
11
|
-
}
|
12
|
-
|
13
|
-
when :struct
|
14
|
-
yield("", self)
|
15
|
-
field_value.each_by_flat_path {|v, x|
|
16
|
-
yield(v, x)
|
17
|
-
}
|
18
|
-
|
19
|
-
when :list
|
20
|
-
yield("", self)
|
21
|
-
field_value.each_with_index {|item, index|
|
22
|
-
yield("[" + index.to_s + "]", item)
|
23
|
-
item.each_by_flat_path("/") {|v, x|
|
24
|
-
yield("[" + index.to_s + "]" + v, x)
|
25
|
-
}
|
26
|
-
}
|
27
|
-
|
28
|
-
else
|
29
|
-
yield("", self)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
#:startdoc:
|
33
|
-
end
|
34
|
-
|
35
|
-
module NWN::Gff::Struct
|
36
|
-
|
37
|
-
# Iterates this struct, yielding flat, absolute
|
38
|
-
# pathes and the Gff::Field for each element found.
|
39
|
-
|
40
|
-
# Example:
|
41
|
-
# "/AddCost" => {"type"=>:dword, ..}
|
42
|
-
def each_by_flat_path prefix = "/", &block
|
43
|
-
sort.each {|label, field|
|
44
|
-
field.each_by_flat_path do |ll, lv|
|
45
|
-
yield(prefix + label + ll, lv)
|
46
|
-
end
|
47
|
-
}
|
48
|
-
end
|
49
|
-
|
50
|
-
# Retrieve an object from within the given tree.
|
51
|
-
# Path is a slash-separated destination, given as
|
52
|
-
# a string
|
53
|
-
#
|
54
|
-
# Prefixed/postfixed slashes are optional.
|
55
|
-
#
|
56
|
-
# Examples:
|
57
|
-
# /
|
58
|
-
# /AddCost
|
59
|
-
# /PropertiesList/
|
60
|
-
# /PropertiesList[0]/CostValue
|
61
|
-
def by_path path
|
62
|
-
struct = self
|
63
|
-
current_path = ""
|
64
|
-
path = path.split('/').map {|v| v.strip }.reject {|v| v.empty?}.join('/')
|
65
|
-
|
66
|
-
path.split('/').each {|v|
|
67
|
-
if v =~ /^(.+?)\[(\d+)\]$/
|
68
|
-
v, index = $1, $2
|
69
|
-
end
|
70
|
-
|
71
|
-
struct = struct[v]
|
72
|
-
if index
|
73
|
-
struct.field_type == :list or raise NWN::Gff::GffPathInvalidError,
|
74
|
-
"Specified a list offset for a non-list item: #{v}[#{index}]."
|
75
|
-
|
76
|
-
struct = struct.field_value[index.to_i]
|
77
|
-
end
|
78
|
-
|
79
|
-
raise NWN::Gff::GffPathInvalidError,
|
80
|
-
"Cannot find a path to /#{path} (at: /#{current_path})." unless struct
|
81
|
-
|
82
|
-
current_path += v
|
83
|
-
}
|
84
|
-
|
85
|
-
struct
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|