nwn-lib 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
data/BINARIES CHANGED
@@ -43,6 +43,6 @@ Usage is simple: just pass all old .yml files to the script, it will convert the
43
43
  in-place (read: make a backup!).
44
44
 
45
45
  This uses nwn-gff-convert and nwn-gff, so all environment variables are taken into
46
- consideration. You will want to point NWN_LIB_INFER_DATA_FILE to something useful.
46
+ consideration.
47
47
 
48
48
  Backup and testing is ADVISED!
data/CHANGELOG CHANGED
@@ -164,4 +164,42 @@ Bernhard Stoeckner (14):
164
164
  Scripting: ask: fix return value of hash and arrays
165
165
  TwoDA: add disclaimer for Cache references
166
166
  TwoDA: add Table#[], Table#[]=
167
-
167
+ 0.4.5-rel
168
+
169
+ === 0.4.6
170
+ Bernhard Stoeckner <elven@swordcoast.net> (26):
171
+ bin/nwn-dsl: always print backtraces
172
+ tests: add rspec stub for later test introduction
173
+ Field: complete valid_for?, add checks in readers, add rspec
174
+ Field: #path prints proper list indices
175
+ ResourceManager: generic implementation as per bioware docs
176
+ TwoDA: read 2da header with arbitary spaces between magic and version
177
+ TwoDA: make id mismatch parsing more robust
178
+ TwoDA: nwn does not fill in missing row IDs
179
+ TwoDA: fix typo preventing #to_2da with NWN_LIB_2DA_NEWLINE absent
180
+ TwoDA: only print to $stderr when -d/$DEBUG is set
181
+ TwoDA: do not raise error on misshaped ID column, add documentation
182
+ TwoDA: do not compact multiple nonquoted cells in last column
183
+ TwoDA: add specs
184
+ Erf: skip over lid and strz to read locstrs correctly
185
+ Erf: seek to offsets instead of depending on constants, handle IOErrors
186
+ Erf: add specs
187
+ Tlk: fix reading last strref in a tlk
188
+ Tlk: add specs
189
+ Cexolocstr: add specs
190
+ Struct: .new accepts a block
191
+ Struct: add specs
192
+ Gff: add specs
193
+ feature kill: remove type/value inferring, NWN_LIB_INFER_*
194
+ Revert "add env setting NWN_LIB_FILTER_EMPTY_EXOLOCSTR"
195
+ Rakefile/rdoc: use mislav-hanna if available
196
+ update all documentation to reflect current situation
197
+ 0.4.6-rel
198
+
199
+ This release changes a few features; most prominent of all is the
200
+ infer mechanism - it is removed completely for sanity reasons.
201
+
202
+ Also, quite a few bugfixes found their way into this release, thanks
203
+ to the newly-added specs.
204
+
205
+ Please browse the commit log for a full list of changes.
data/CHEATSHEET CHANGED
@@ -1,9 +1,23 @@
1
1
  ==== Convert all item files in the current directory to yaml and back
2
2
 
3
- for x in *.uti; do
4
- nwn-gff-convert -i"$x" -o"$x.yml" -lg -ky
5
- done
3
+ for x in *.uti; do
4
+ nwn-gff -i"$x" -o"$x.yml"
5
+ done
6
6
 
7
- for x in *.uti.yml; do
8
- nwn-gff-convert -i"$x" -o"$(basename $x .yml)" -ly -kg
9
- done
7
+ for x in *.uti.yml; do
8
+ nwn-gff -i"$x" -o"$(basename $x .yml)"
9
+ done
10
+
11
+ ==== A Makefile that rebuilds only changed resources
12
+
13
+ This can be done with a GNU Makefile too, with the added benefit that
14
+ it will keep track of changes automagically and only rebuild those resources
15
+ that you have changed (saving you a lot of time).
16
+
17
+ yml = $(wildcard *.yml)
18
+ gff = $(basename $(yml))
19
+
20
+ all: $(gff)
21
+
22
+ % : %.yml
23
+ nwn-gff -i $< -o $@
data/README CHANGED
@@ -4,36 +4,41 @@ This package provides a library for reading, changing, and writing common file f
4
4
 
5
5
  They should work with NWN2 just as well, since the file format specifications did not change.
6
6
 
7
- === Upgrade from 0.3.6 to 0.4.x
8
7
 
9
- With the release of 0.4.0, the API changed significantly. Previous yaml dumps made with 0.3.x are INCOMPATIBLE, and so are all scripts.
10
- I can't help you with your API bindings, but for your YAML dumps, a converter script has been provided (see BINARIES).
8
+ === Features of nwn-lib
11
9
 
12
- === A word on version numbers
10
+ ==== nwn-lib reads and writes the following file formats (hopefully bug-free!), both with an API and useful command-line tools:
13
11
 
14
- Please consider all version releases below 1.0.0 to be unstable, even though the code is fully functional - further API changes may not be avoidable between major revisions - such as is the case with 0.3 -> 0.4.
12
+ * GFF 3.2 (are, git, gic, dlg, itp, ifo, jrl, fac, ssf, ut*, among others)
13
+ * ERF (mod, hak, erf, among others)
14
+ * 2DA V2.0
15
+ * TLK
15
16
 
16
- === Features of nwn-lib
17
+ ==== nwn-lib can read and write the following representations of GFF data:
17
18
 
18
- * a feature-complete parser and generator of valid GFF V3.2 data
19
- * shell scripts and tools to simplify your life (see BINARIES)
20
19
  * kivinen-style ("gffprint.pl") presentation of data
21
20
  * yaml presentation of data
22
21
  * ruby-native marshalling of gff data
22
+
23
+ ==== Also in the box:
24
+
25
+ * shell scripts and tools to simplify your life (see BINARIES)
23
26
  * extensive developer API
24
27
  * a powerful get-out-of-my-way scripting system for data transformation (see SCRIPTING)
25
- * guessing of field-types and -values for shorter plaintext data dumps (see TYPE_AND_VALUE_INFERRING)
26
28
 
27
- Also in the box:
28
29
 
29
- * a CHEATSHEET showing off some cool tricks
30
- * some gadgetry for working with 2da files
30
+ === Upgrade from 0.3.6 to 0.4.x
31
+
32
+ With the release of 0.4.0, the API changed significantly. Previous yaml dumps made with 0.3.x are INCOMPATIBLE, and so are all scripts.
33
+ I can't help you with your API bindings, but for your YAML dumps, a converter script has been provided (see BINARIES).
34
+
31
35
 
32
36
  === Attention Unicode/UTF-users
33
37
 
34
38
  ruby 1.8 does not support character sets natively, and as such nwn-gff-irb will <b>FAIL</b> to encode non-standard characters properly on non-latin1 shells.
35
39
  This will be worked around in a future release until the release of ruby 1.9, which will provide native charset support.
36
40
 
41
+
37
42
  === Quickstart
38
43
 
39
44
  To use it, simply install the gem (available on rubyforge):
@@ -45,4 +50,16 @@ And do the following in a script of your own devising:
45
50
  require 'rubygems'
46
51
  require 'nwn/all'
47
52
 
53
+ Also, Read BINARIES.
54
+
48
55
  For nwn-lib scripts, see SCRIPTING.
56
+
57
+ For using the developer API, I suggest you start reading NWN::Gff::Struct.
58
+
59
+ === Latest code & developer contact
60
+
61
+ The latest source is available through git[http://git.swordcoast.net/?p=nwn/nwn-lib.git;a=summary].
62
+
63
+ All stable releases are tagged properly.
64
+
65
+ You can reach me via email[mailto:elven@swordcoast.net].
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require "rake"
2
2
  require "rake/clean"
3
3
  require "rake/gempackagetask"
4
- require "rake/rdoctask"
4
+ require "hanna/rdoctask" rescue require "rake/rdoctask"
5
5
  require "fileutils"
6
6
  include FileUtils
7
7
 
@@ -9,13 +9,13 @@ include FileUtils
9
9
  # Configuration
10
10
  ##############################################################################
11
11
  NAME = "nwn-lib"
12
- VERS = "0.4.5"
12
+ VERS = "0.4.6"
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", "DATA_STRUCTURES", "SCRIPTING", "SETTINGS", "TYPE_VALUE_INFERRING", "CHEATSHEET", "CHANGELOG", "COPYING"]
18
+ DOCS = ["README", "BINARIES", "SCRIPTING", "SETTINGS", "CHEATSHEET", "CHANGELOG", "COPYING"]
19
19
 
20
20
  Rake::RDocTask.new do |rdoc|
21
21
  rdoc.rdoc_dir = "rdoc"
data/SETTINGS CHANGED
@@ -1,82 +1,16 @@
1
1
  There are various environment variables you can configure to adjust various parts of nwn-lib.
2
2
 
3
- <b>All of them are optional!</b>
3
+ <b>All of them are optional, and, in fact, can waste your time!</b>
4
4
 
5
5
  Under linux, just add them to your shell environment (usually .bashrc), like so:
6
6
 
7
- export NWN_LIB_INFER_DATA_FILE=/usr/lib/ruby/gems/1.8/gems/nwn-lib-0.4.0/data/gff-common-nwn1.yaml
7
+ export NWN_LIB_FILTER_EMPTY_EXOLOCSTR=1
8
8
 
9
9
 
10
- == NWN_LIB_INFER_DATA_FILE
11
-
12
- The path to the type/value inferring data file. See TYPE_VALUE_INFERRING for a definition.
13
-
14
- Please be advised that inferring support for YAML is <b>EXPERIMENTAL</b> and may result in
15
- <b>module and gff file corruption</b>.
16
-
17
- == NWN_LIB_DONT_COMPACT_FIELDS
18
-
19
- Set to non-nil ("1" will do) to prevent nwn-lib from compacting scalar fields into a more-readable
20
- (but still fully parseable) format, if type inferring data is available.
21
-
22
- === Without compacting
23
- ItemList:
24
- value:
25
- - !nwn-lib.elv.es,2008-12/struct
26
- __data_type: UTC/ItemList
27
- __struct_id: 0
28
- InventoryRes: {value: herb053}
29
- PaletteID: {value: 6}
30
- SkillList: [{value: 0}, {value: 0}, {value: 0}, {value: 0}, ...
31
-
32
- === With compacting
33
- ItemList:
34
- - !nwn-lib.elv.es,2008-12/struct
35
- __data_type: UTC/ItemList
36
- InventoryRes: herb053
37
- PaletteID: 6
38
- SkillList: [0, 0, 0, 0, 0, 0, 2, 0, 0, 0 ...
39
-
40
-
41
- == NWN_LIB_DONT_COMPACT_LIST_STRUCTS
42
-
43
- Setting this to non-nil ("1" will do) will prevent nwn-lib from compacting lists that contain
44
- structs, if type inferring data is available.
45
-
46
- === Without compacting
47
- SkillList:
48
- - !nwn-lib.elv.es,2008-12/struct {__data_type: UTC/SkillList, Rank: 0}
49
- - !nwn-lib.elv.es,2008-12/struct {__data_type: UTC/SkillList, Rank: 0}
50
- - !nwn-lib.elv.es,2008-12/struct {__data_type: UTC/SkillList, Rank: 0}
51
- - !nwn-lib.elv.es,2008-12/struct {__data_type: UTC/SkillList, Rank: 0}
52
- - !nwn-lib.elv.es,2008-12/struct {__data_type: UTC/SkillList, Rank: 0}
53
- - !nwn-lib.elv.es,2008-12/struct {__data_type: UTC/SkillList, Rank: 0}
54
- - !nwn-lib.elv.es,2008-12/struct {__data_type: UTC/SkillList, Rank: 2}
55
- - !nwn-lib.elv.es,2008-12/struct {__data_type: UTC/SkillList, Rank: 0}
56
- ...
57
-
58
- === With compacting
59
- SkillList: [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, ...
60
-
61
-
62
- == NWN_LIB_CLEAR_KNOWN_VALUES
63
-
64
- Set to non-nil ("1" will do) to make nwn-lib omit fields that resolve to default values
65
- as configured in $NWN_LIB_INFER_DATA_FILE.
66
-
67
- The default is to not omit known-value data fields.
68
-
69
- == NWN_LIB_FILTER_EMPTY_EXOLOCSTR
70
-
71
- Set to non-nil ("1" will do) to make nwn-lib filter out empty exolocstr fields from
72
- input files on reading.
73
-
74
- The default is to keep them as-is.
75
-
76
10
  == NWN_LIB_2DA_LOCATION
77
11
 
78
12
  Set to a path containing all 2da files to initialize the 2da cache. This is needed for
79
- most interactive helpers and a few type infer gizmos.
13
+ most interactive helpers and a few gizmos, and, of course, for TwoDA::Cache.
80
14
 
81
15
  == NWN_LIB_TWODA_NEWLINE
82
16
 
data/bin/nwn-dsl CHANGED
@@ -6,9 +6,6 @@ require 'nwn/all'
6
6
  $backtrace = false
7
7
  OptionParser.new do |o|
8
8
  o.banner = "Usage: nwn-dsl [options] <script> -- [arguments to script]"
9
- o.on "-b", "--backtrace", "Show a backtrace on error" do
10
- $backtrace = true
11
- end
12
9
  end.parse!
13
10
 
14
11
  fail "Not enough arguments (try -h)." unless ARGV.size > 0
@@ -19,9 +16,7 @@ begin
19
16
  NWN::Gff::Scripting.run_script(IO.read($SCRIPT), nil, ARGV)
20
17
  rescue => e
21
18
  $stderr.puts e.message
22
- if $backtrace
23
- $stderr.puts ""
24
- $stderr.puts " " + e.backtrace.join("\n")
25
- end
19
+ $stderr.puts ""
20
+ $stderr.puts " " + e.backtrace.join("\n")
26
21
  exit 1
27
22
  end
data/lib/nwn/all.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'nwn/twoda'
2
+ require 'nwn/res'
2
3
  require 'nwn/gff'
3
4
  require 'nwn/tlk'
4
5
  require 'nwn/erf'
data/lib/nwn/erf.rb CHANGED
@@ -4,123 +4,10 @@ module NWN
4
4
  module Erf
5
5
  ValidTypes = %w{ERF HAK MOD}
6
6
 
7
- Extensions = {
8
- 'res' => 0,
9
- 'bmp' => 1,
10
- 'mve' => 2,
11
- 'tga' => 3,
12
- 'wav' => 4,
13
- 'wfx' => 5,
14
- 'plt' => 6,
15
- 'ini' => 7,
16
- 'mp3' => 8,
17
- 'mpg' => 9,
18
- 'txt' => 10,
19
- 'plh' => 2000,
20
- 'tex' => 2001,
21
- 'mdl' => 2002,
22
- 'thg' => 2003,
23
- 'fnt' => 2005,
24
- 'lua' => 2007,
25
- 'slt' => 2008,
26
- 'nss' => 2009,
27
- 'ncs' => 2010,
28
- 'mod' => 2011,
29
- 'are' => 2012,
30
- 'set' => 2013,
31
- 'ifo' => 2014,
32
- 'bic' => 2015,
33
- 'wok' => 2016,
34
- '2da' => 2017,
35
- 'tlk' => 2018,
36
- 'txi' => 2022,
37
- 'git' => 2023,
38
- 'bti' => 2024,
39
- 'uti' => 2025,
40
- 'btc' => 2026,
41
- 'utc' => 2027,
42
- 'dlg' => 2029,
43
- 'itp' => 2030,
44
- 'btt' => 2031,
45
- 'utt' => 2032,
46
- 'dds' => 2033,
47
- 'bts' => 2034,
48
- 'uts' => 2035,
49
- 'ltr' => 2036,
50
- 'gff' => 2037,
51
- 'fac' => 2038,
52
- 'bte' => 2039,
53
- 'ute' => 2040,
54
- 'btd' => 2041,
55
- 'utd' => 2042,
56
- 'btp' => 2043,
57
- 'utp' => 2044,
58
- 'dft' => 2045,
59
- 'gic' => 2046,
60
- 'gui' => 2047,
61
- 'css' => 2048,
62
- 'ccs' => 2049,
63
- 'btm' => 2050,
64
- 'utm' => 2051,
65
- 'dwk' => 2052,
66
- 'pwk' => 2053,
67
- 'btg' => 2054,
68
- 'utg' => 2055,
69
- 'jrl' => 2056,
70
- 'sav' => 2057,
71
- 'utw' => 2058,
72
- '4pc' => 2059,
73
- 'ssf' => 2060,
74
- 'hak' => 2061,
75
- 'nwm' => 2062,
76
- 'bik' => 2063,
77
- 'ndb' => 2064,
78
- 'ptm' => 2065,
79
- 'ptt' => 2066,
80
- 'bak' => 2067,
81
- 'osc' => 3000,
82
- 'usc' => 3001,
83
- 'trn' => 3002,
84
- 'utr' => 3003,
85
- 'uen' => 3004,
86
- 'ult' => 3005,
87
- 'sef' => 3006,
88
- 'pfx' => 3007,
89
- 'cam' => 3008,
90
- 'lfx' => 3009,
91
- 'bfx' => 3010,
92
- 'upe' => 3011,
93
- 'ros' => 3012,
94
- 'rst' => 3013,
95
- 'ifx' => 3014,
96
- 'pfb' => 3015,
97
- 'zip' => 3016,
98
- 'wmp' => 3017,
99
- 'bbx' => 3018,
100
- 'tfx' => 3019,
101
- 'wlk' => 3020,
102
- 'xml' => 3021,
103
- 'scc' => 3022,
104
- 'ptx' => 3033,
105
- 'ltx' => 3034,
106
- 'trx' => 3035,
107
- 'mdb' => 4000,
108
- 'mda' => 4001,
109
- 'spt' => 4002,
110
- 'gr2' => 4003,
111
- 'fxa' => 4004,
112
- 'fxe' => 4005,
113
- 'jpg' => 4007,
114
- 'pwc' => 4008,
115
- 'ids' => 9996,
116
- 'erf' => 9997,
117
- 'bif' => 9998,
118
- 'key' => 9999,
119
- }.freeze
7
+ # This reads and writes NWN::Resources::Container
8
+ # as valid ERF binary data.
9
+ class Erf < NWN::Resources::Container
120
10
 
121
- class Erf
122
-
123
- attr_accessor :content
124
11
  attr_accessor :localized_strings
125
12
  attr_accessor :description_str_ref
126
13
 
@@ -131,74 +18,16 @@ module NWN
131
18
 
132
19
  # Create a new Erf object, optionally reading a existing file from +io+.
133
20
  def initialize io = nil
134
- @content = []
21
+ super()
135
22
  @localized_strings = {}
136
23
  @io = io
137
24
  @file_type, @file_version = "ERF", "V1.0"
138
25
  @year = Time.now.year
139
26
  @description_str_ref = 0xffffffff
140
- @day_of_year = Time.now.yday # strftime("%j").to_i
27
+ @day_of_year = Time.now.yday
141
28
  read_from io if io
142
29
  end
143
30
 
144
- def add filename
145
- @content << ContentObject.new_from(filename)
146
- end
147
-
148
- def has?(filename)
149
- base = File.basename(filename)
150
- @content.each {|f|
151
- return true if f.filename.downcase == base.downcase
152
- }
153
- return false
154
- end
155
-
156
- class ContentObject
157
- attr_accessor :resref
158
- attr_accessor :res_type
159
- attr_accessor :io
160
- attr_accessor :offset
161
- attr_accessor :size_override
162
-
163
- def self.new_from filename
164
- stat = File.stat(filename)
165
- base = File.basename(filename).split(".")[0..-2].join(".")
166
- ext = File.extname(filename)[1..-1]
167
- res_type = NWN::Erf::Extensions[ext] or raise ArgumentError,
168
- "Not a valid extension: #{ext.inspect} (while packing #{filename})"
169
-
170
- ContentObject.new(base, res_type, filename, 0, stat.size)
171
- end
172
-
173
- def initialize resref, res_type, io = nil, offset = nil, size = nil
174
- @resref, @res_type = resref, res_type
175
- @io, @offset = io, offset
176
- @size_override = size
177
- end
178
-
179
- # Get the size in bytes of this object.
180
- def size
181
- @size_override || (@io.is_a?(IO) ? @io.stat.size : File.stat(@io).size)
182
- end
183
-
184
- def get
185
- if @io.is_a?(IO)
186
- @io.seek(@offset) if @offset
187
- @io.read(self.size)
188
- else
189
- IO.read(@io)
190
- end
191
- end
192
-
193
- def filename
194
- @resref + "." + self.extension
195
- end
196
-
197
- def extension
198
- NWN::Erf::Extensions.index(@res_type)
199
- end
200
- end
201
-
202
31
  private
203
32
 
204
33
  def read_from io
@@ -219,42 +48,40 @@ module NWN
219
48
 
220
49
  if @file_version == "V1.0"
221
50
  @filename_length = 16
222
- # elsif version == "V1.1"
223
- # @filename_length = 32
224
51
  else
225
52
  raise IOError, "Invalid erf version: #{@file_version}"
226
53
  end
227
54
 
228
- raise IOError, "key list not after locstr list" unless
229
- offset_to_keys == offset_to_locstr + locstr_size
230
-
231
- raise IOError, "Offset to locstr list is not after header" if
232
- offset_to_locstr != 160
233
-
55
+ @io.seek(offset_to_locstr)
234
56
  locstr = @io.read(locstr_size)
235
- raise IOError, "Cannot read locstr list" unless
236
- locstr.size == locstr_size
237
57
 
238
58
  for lstr in 0...locstr_count do
59
+ raise IOError, "locstr table does not contain enough entries or locstr_size is too small" if
60
+ locstr.nil? || locstr.size < 8
61
+
239
62
  lid, strsz = locstr.unpack("V V")
240
- str = locstr.unpack("a#{strsz}")[0]
241
- $stderr.puts "Expected string size does not match actual string size (want: #{strsz}, got #{str.size} of #{str.inspect})" if
242
- strsz != str.size
63
+ str = locstr.unpack("x8 a#{strsz}")[0]
64
+ raise IOError,
65
+ "Expected locstr size does not match actual string size (want: #{strsz}, got #{str.size} of #{str.inspect})" if
66
+ strsz != str.size
67
+
243
68
  @localized_strings[lid] = str
244
69
  locstr = locstr[8 + str.size .. -1]
245
- raise IOError, "locstr table does not contain enough entries (want: #{locstr_count}, got: #{lstr + 1})" if locstr.nil? &&
246
- lstr + 1 < locstr_count
247
70
  end
248
71
 
249
72
  keylist_entry_size = @filename_length + 4 + 2 + 2
73
+ @io.seek(offset_to_keys)
250
74
  keylist = @io.read(keylist_entry_size * entry_count)
75
+ raise IOError, "keylist too short" if keylist.size != keylist_entry_size * entry_count
251
76
  keylist = keylist.unpack("A16 V v v" * entry_count)
252
77
  keylist.each_slice(4) {|resref, res_id, res_type, unused|
253
- @content << ContentObject.new(resref, res_type, @io)
78
+ @content << NWN::Resources::ContentObject.new(resref, res_type, @io)
254
79
  }
255
80
 
256
81
  resourcelist_entry_size = 4 + 4
82
+ @io.seek(offset_to_res)
257
83
  resourcelist = @io.read(resourcelist_entry_size * entry_count)
84
+ raise IOError, "resource list too short" if resourcelist.size != resourcelist_entry_size * entry_count
258
85
  resourcelist = resourcelist.unpack("I I" * entry_count)
259
86
  _index = -1
260
87
  resourcelist.each_slice(2) {|offset, size|