nwn-lib 0.4.5 → 0.4.6
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/BINARIES +1 -1
- data/CHANGELOG +39 -1
- data/CHEATSHEET +20 -6
- data/README +29 -12
- data/Rakefile +3 -3
- data/SETTINGS +3 -69
- data/bin/nwn-dsl +2 -7
- data/lib/nwn/all.rb +1 -0
- data/lib/nwn/erf.rb +19 -192
- data/lib/nwn/gff.rb +0 -1
- data/lib/nwn/gff/field.rb +53 -14
- data/lib/nwn/gff/reader.rb +2 -2
- data/lib/nwn/gff/struct.rb +27 -9
- data/lib/nwn/res.rb +275 -0
- data/lib/nwn/settings.rb +0 -4
- data/lib/nwn/tlk.rb +1 -1
- data/lib/nwn/twoda.rb +36 -17
- data/lib/nwn/yaml.rb +13 -198
- data/spec/cexolocstr_spec.rb +15 -0
- data/spec/erf_spec.rb +87 -0
- data/spec/field_spec.rb +21 -0
- data/spec/gff_spec.rb +22 -0
- data/spec/res_spec.rb +59 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/struct_spec.rb +61 -0
- data/spec/tlk_spec.rb +47 -0
- data/spec/twoda_spec.rb +146 -0
- data/spec/wellformed_gff.binary +0 -0
- metadata +13 -8
- data/DATA_STRUCTURES +0 -50
- data/TYPE_VALUE_INFERRING +0 -93
- data/data/gff-common-nwn1.yaml +0 -982
- data/lib/nwn/infer.rb +0 -125
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.
|
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
|
-
|
4
|
-
|
5
|
-
|
3
|
+
for x in *.uti; do
|
4
|
+
nwn-gff -i"$x" -o"$x.yml"
|
5
|
+
done
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
30
|
-
|
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.
|
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", "
|
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
|
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
|
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
|
-
|
23
|
-
|
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
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
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
242
|
-
strsz
|
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|
|