nwn-lib 0.4.2 → 0.4.3
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 +8 -0
- data/CHANGELOG +6 -0
- data/Rakefile +2 -2
- data/bin/nwn-erf +184 -0
- data/lib/nwn/all.rb +2 -0
- data/lib/nwn/erf.rb +295 -0
- metadata +5 -2
data/BINARIES
CHANGED
|
@@ -9,6 +9,14 @@ for help, it should be self-explanatory.
|
|
|
9
9
|
|
|
10
10
|
There are some usage examples on the CHEATSHEET.
|
|
11
11
|
|
|
12
|
+
== nwn-erf
|
|
13
|
+
|
|
14
|
+
nwn-erf can pack/unpack all mod, hak, erf and nwm files.
|
|
15
|
+
|
|
16
|
+
Type
|
|
17
|
+
nwn-erf -h
|
|
18
|
+
for help.
|
|
19
|
+
|
|
12
20
|
== nwn-irb
|
|
13
21
|
|
|
14
22
|
nwn-irb is a interactive shell preloading all relevant libs, and optionally
|
data/CHANGELOG
CHANGED
|
@@ -130,3 +130,9 @@ Bernhard Stoeckner <elven@swordcoast.net> (10):
|
|
|
130
130
|
add *.itp to GuessFormats
|
|
131
131
|
Tlk: basic talktable editing and writing
|
|
132
132
|
0.4.2-rel
|
|
133
|
+
|
|
134
|
+
=== 0.4.3
|
|
135
|
+
Bernhard Stoeckner <elven@swordcoast.net> (2):
|
|
136
|
+
NWN::Erf: basic reading/writing library + tar-like binary
|
|
137
|
+
add tlk.rb to nwn/all.rb
|
|
138
|
+
0.4.3-rel
|
data/Rakefile
CHANGED
|
@@ -9,7 +9,7 @@ include FileUtils
|
|
|
9
9
|
# Configuration
|
|
10
10
|
##############################################################################
|
|
11
11
|
NAME = "nwn-lib"
|
|
12
|
-
VERS = "0.4.
|
|
12
|
+
VERS = "0.4.3"
|
|
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', \
|
|
@@ -39,7 +39,7 @@ spec = Gem::Specification.new do |s|
|
|
|
39
39
|
s.author = "Bernhard Stoeckner"
|
|
40
40
|
s.email = "elven@swordcoast.net"
|
|
41
41
|
s.homepage = "http://nwn-lib.elv.es"
|
|
42
|
-
s.executables = ["nwn-gff", "nwn-dsl", "nwn-irb"]
|
|
42
|
+
s.executables = ["nwn-gff", "nwn-erf", "nwn-dsl", "nwn-irb"]
|
|
43
43
|
s.required_ruby_version = ">= 1.8.4"
|
|
44
44
|
s.files = %w(COPYING CHANGELOG README Rakefile) + Dir.glob("{bin,doc,spec,lib,tools,scripts,data}/**/*")
|
|
45
45
|
s.require_path = "lib"
|
data/bin/nwn-erf
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'optparse'
|
|
4
|
+
require 'nwn/all'
|
|
5
|
+
require 'tempfile'
|
|
6
|
+
|
|
7
|
+
$action = nil
|
|
8
|
+
$verbose = false
|
|
9
|
+
$type = 'ERF'
|
|
10
|
+
$allow_duplicates = false
|
|
11
|
+
$descriptions = {}
|
|
12
|
+
|
|
13
|
+
begin OptionParser.new do |o|
|
|
14
|
+
o.banner = "Usage: nwn-erf <options> [FILEs] ..."
|
|
15
|
+
|
|
16
|
+
o.on "-f FILE", "Specify archive name (instead of stdin/stdout)" do |file|
|
|
17
|
+
$file = file
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
o.separator " "
|
|
21
|
+
|
|
22
|
+
o.on "-t", "--list", "List erf contents. Use -v for attributes." do
|
|
23
|
+
$action = :t
|
|
24
|
+
end
|
|
25
|
+
o.on "-c", "--create", "Create a new archive with the given files as contents." do
|
|
26
|
+
$action = :c
|
|
27
|
+
end
|
|
28
|
+
o.on "-x", "--extract", "Extract all files to current directory." do
|
|
29
|
+
$action = :x
|
|
30
|
+
end
|
|
31
|
+
o.on "-a", "--add", "Add files to the given archive.",
|
|
32
|
+
"This is an expensive operation, a full archive rebuild is required." do
|
|
33
|
+
$action = :a
|
|
34
|
+
end
|
|
35
|
+
o.on "-r", "--remove", "Remove files from the given archive.",
|
|
36
|
+
"This is an expensive operation, a full archive rebuild is required." do
|
|
37
|
+
$action = :r
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
o.separator " "
|
|
41
|
+
|
|
42
|
+
o.on "-D TEXT", "--description", "Set a description TEXT",
|
|
43
|
+
"Only useful with -c, -a, -r." do |text|
|
|
44
|
+
$descriptions[0] = text
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
o.on "--type TYPE", "Specify 3 or 4-letter archive type (defaults to 'HAK')" do |t|
|
|
48
|
+
$type = t
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
o.on "-H" , "--hak", "Shorthand for --type HAK" do
|
|
52
|
+
$type = 'HAK'
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
o.on "-E" , "--erf", "Shorthand for --type ERF (default)" do
|
|
56
|
+
$type = 'ERF'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
o.on "-M" , "--mod", "Shorthand for --type MOD" do
|
|
60
|
+
$type = 'MOD'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
o.separator " "
|
|
64
|
+
o.separator "Hacks:"
|
|
65
|
+
|
|
66
|
+
o.on "--allow-duplicates", "Allow packaging of duplicate filenames" do
|
|
67
|
+
$allow_duplicates = true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
o.separator " "
|
|
71
|
+
|
|
72
|
+
o.on_tail "-h", "--help", "Show this crud" do
|
|
73
|
+
$stderr.puts o
|
|
74
|
+
exit 1
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
o.on_tail "-v", "--verbose", "be verbose" do |v|
|
|
78
|
+
$verbose = v
|
|
79
|
+
end
|
|
80
|
+
end.parse!
|
|
81
|
+
rescue => ee
|
|
82
|
+
$stderr.puts ee.to_s
|
|
83
|
+
$stderr.puts ee.backtrace.join("\n")
|
|
84
|
+
exit 1
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def input filename = nil
|
|
89
|
+
if $file.nil?
|
|
90
|
+
yield $stdin
|
|
91
|
+
else
|
|
92
|
+
File.open(filename || $file, "r") {|f| yield f}
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def output mode = "w", filename = nil
|
|
97
|
+
if $file.nil?
|
|
98
|
+
yield $stdout
|
|
99
|
+
else
|
|
100
|
+
File.open(filename || $file, mode) {|f| yield f}
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
case $action
|
|
105
|
+
when :t
|
|
106
|
+
input {|f|
|
|
107
|
+
erf = NWN::Erf::Erf.new(f)
|
|
108
|
+
$stderr.puts "# %-4s %14s %16s %-10s %s" % %w{type offset size date filename} if $verbose
|
|
109
|
+
erf.content.each {|c|
|
|
110
|
+
if !$verbose
|
|
111
|
+
$stderr.puts "%s" % [c.filename]
|
|
112
|
+
else
|
|
113
|
+
$stderr.puts "%4d %16d %16d %10s %s" % [
|
|
114
|
+
c.res_type, c.offset, c.size,
|
|
115
|
+
Date.ordinal(1900 + erf.year, erf.day_of_year).strftime("%Y-%m-%d"),
|
|
116
|
+
c.filename
|
|
117
|
+
]
|
|
118
|
+
end
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
when :x
|
|
123
|
+
input {|f|
|
|
124
|
+
erf = NWN::Erf::Erf.new(f)
|
|
125
|
+
erf.content.each {|c|
|
|
126
|
+
$stderr.puts "%s" % [c.filename] if $verbose
|
|
127
|
+
File.open(c.filename, "w") {|ff|
|
|
128
|
+
ff.write(c.get)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
when :c
|
|
134
|
+
erf = NWN::Erf::Erf.new
|
|
135
|
+
erf.file_type = $type if $type
|
|
136
|
+
|
|
137
|
+
if $descriptions
|
|
138
|
+
erf.localized_strings.merge! $descriptions
|
|
139
|
+
erf.description_str_ref = 0
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
ARGV.each {|a|
|
|
143
|
+
$stderr.puts File.basename(a) if $verbose
|
|
144
|
+
raise ArgumentError, "#{File.basename(a)} already present in erf." if
|
|
145
|
+
!$allow_duplicates && erf.has?(a)
|
|
146
|
+
erf.add a
|
|
147
|
+
}
|
|
148
|
+
output {|f| erf.write_to(f) }
|
|
149
|
+
|
|
150
|
+
when :a, :r
|
|
151
|
+
input do |infile|
|
|
152
|
+
erf = NWN::Erf::Erf.new(infile)
|
|
153
|
+
|
|
154
|
+
if $descriptions
|
|
155
|
+
erf.localized_strings.merge! $descriptions
|
|
156
|
+
erf.description_str_ref = 0
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
ARGV.each {|arg|
|
|
160
|
+
case $action
|
|
161
|
+
when :a
|
|
162
|
+
raise ArgumentError, "#{File.basename(arg)} already present in erf." if
|
|
163
|
+
!$allow_duplicates && erf.has?(arg)
|
|
164
|
+
erf.add arg
|
|
165
|
+
|
|
166
|
+
when :r
|
|
167
|
+
erf.content.reject! {|con|
|
|
168
|
+
con.filename.downcase == arg.downcase
|
|
169
|
+
}
|
|
170
|
+
end
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
tempfile = Tempfile.new("nwn-erf", File.dirname($file || "."))
|
|
174
|
+
output("w", tempfile.path) do |f|
|
|
175
|
+
erf.write_to(f)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
FileUtils.mv(tempfile.path, $file) unless $file.nil?
|
|
179
|
+
tempfile.close
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
else
|
|
183
|
+
raise ArgumentError, "You need to specify a mode of operation (try -h)."
|
|
184
|
+
end
|
data/lib/nwn/all.rb
CHANGED
data/lib/nwn/erf.rb
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
require 'enumerator'
|
|
2
|
+
|
|
3
|
+
module NWN
|
|
4
|
+
module Erf
|
|
5
|
+
ValidTypes = %w{ERF HAK MOD}
|
|
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
|
|
120
|
+
|
|
121
|
+
class Erf
|
|
122
|
+
|
|
123
|
+
attr_accessor :content
|
|
124
|
+
attr_accessor :localized_strings
|
|
125
|
+
attr_accessor :description_str_ref
|
|
126
|
+
|
|
127
|
+
attr_accessor :file_type
|
|
128
|
+
attr_accessor :file_version
|
|
129
|
+
attr_accessor :day_of_year
|
|
130
|
+
attr_accessor :year
|
|
131
|
+
|
|
132
|
+
# Create a new Erf object, optionally reading a existing file from +io+.
|
|
133
|
+
def initialize io = nil
|
|
134
|
+
@content = []
|
|
135
|
+
@localized_strings = {}
|
|
136
|
+
@io = io
|
|
137
|
+
@file_type, @file_version = "ERF", "V1.0"
|
|
138
|
+
@year = Time.now.year
|
|
139
|
+
@description_str_ref = 0xffffffff
|
|
140
|
+
@day_of_year = Time.now.yday # strftime("%j").to_i
|
|
141
|
+
read_from io if io
|
|
142
|
+
end
|
|
143
|
+
|
|
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
|
+
private
|
|
203
|
+
|
|
204
|
+
def read_from io
|
|
205
|
+
header = @io.read(160)
|
|
206
|
+
raise IOError, "Cannot read header: Not a erf file?" unless
|
|
207
|
+
header && header.size == 160
|
|
208
|
+
|
|
209
|
+
@file_type, @file_version,
|
|
210
|
+
locstr_count, locstr_size,
|
|
211
|
+
entry_count,
|
|
212
|
+
offset_to_locstr, offset_to_keys,
|
|
213
|
+
offset_to_res,
|
|
214
|
+
@year, @day_of_year, @description_str_ref = header.
|
|
215
|
+
unpack("A4 A4 VV VV VV VV V a116")
|
|
216
|
+
|
|
217
|
+
raise IOError, "Cannot read erf stream: invalid type #{@file_type.inspect}" unless
|
|
218
|
+
NWN::Erf::ValidTypes.index(@file_type)
|
|
219
|
+
|
|
220
|
+
if @file_version == "V1.0"
|
|
221
|
+
@filename_length = 16
|
|
222
|
+
# elsif version == "V1.1"
|
|
223
|
+
# @filename_length = 32
|
|
224
|
+
else
|
|
225
|
+
raise IOError, "Invalid erf version: #{@file_version}"
|
|
226
|
+
end
|
|
227
|
+
|
|
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
|
+
|
|
234
|
+
locstr = @io.read(locstr_size)
|
|
235
|
+
raise IOError, "Cannot read locstr list" unless
|
|
236
|
+
locstr.size == locstr_size
|
|
237
|
+
|
|
238
|
+
locstrs = locstr.unpack("V V/a*" * locstr_count)
|
|
239
|
+
locstrs.each_slice(3) {|lid, strsz, str|
|
|
240
|
+
raise IOError,
|
|
241
|
+
"Cannot read localized strings table: string size not met (want: #{strsz}, got #{str.size})" if
|
|
242
|
+
str.size != strsz
|
|
243
|
+
@localized_strings[lid] = str
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
keylist_entry_size = @filename_length + 4 + 2 + 2
|
|
248
|
+
keylist = @io.read(keylist_entry_size * entry_count)
|
|
249
|
+
keylist = keylist.unpack("A16 V v v" * entry_count)
|
|
250
|
+
keylist.each_slice(4) {|resref, res_id, res_type, unused|
|
|
251
|
+
@content << ContentObject.new(resref, res_type, @io)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
resourcelist_entry_size = 4 + 4
|
|
255
|
+
resourcelist = @io.read(resourcelist_entry_size * entry_count)
|
|
256
|
+
resourcelist = resourcelist.unpack("I I" * entry_count)
|
|
257
|
+
_index = -1
|
|
258
|
+
resourcelist.each_slice(2) {|offset, size|
|
|
259
|
+
_index += 1
|
|
260
|
+
@content[_index].offset = offset
|
|
261
|
+
@content[_index].size_override = size
|
|
262
|
+
}
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
public
|
|
266
|
+
|
|
267
|
+
# Writes this Erf to a io stream.
|
|
268
|
+
def write_to io
|
|
269
|
+
locstr = @localized_strings.map {|x| [x[0], x[1].size, x[1]].pack("V V a*") }.join("")
|
|
270
|
+
keylist = @content.map {|c| [c.resref, @content.index(c), c.res_type, 0].pack("a16 V v v") }.join("")
|
|
271
|
+
reslist = @content.map {|c| [c.offset, c.size].pack("V V") }.join("")
|
|
272
|
+
|
|
273
|
+
offset_to_locstr = 160
|
|
274
|
+
offset_to_keylist = offset_to_locstr + locstr.size
|
|
275
|
+
offset_to_resourcelist = offset_to_keylist + keylist.size
|
|
276
|
+
|
|
277
|
+
header = [@file_type, @file_version,
|
|
278
|
+
@localized_strings.size, locstr.size,
|
|
279
|
+
@content.size,
|
|
280
|
+
offset_to_locstr, offset_to_keylist,
|
|
281
|
+
offset_to_resourcelist,
|
|
282
|
+
@year, @day_of_year, @description_str_ref, ""].pack("A4 A4 VV VV VV VV V a116")
|
|
283
|
+
|
|
284
|
+
io.write(header)
|
|
285
|
+
io.write(locstr)
|
|
286
|
+
io.write(keylist)
|
|
287
|
+
io.write(reslist)
|
|
288
|
+
|
|
289
|
+
@content.each {|c|
|
|
290
|
+
io.write(c.get)
|
|
291
|
+
}
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|
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.3
|
|
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-02-
|
|
12
|
+
date: 2009-02-06 00:00:00 +01:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|
|
@@ -17,6 +17,7 @@ description: a ruby library for accessing Neverwinter Nights resource files
|
|
|
17
17
|
email: elven@swordcoast.net
|
|
18
18
|
executables:
|
|
19
19
|
- nwn-gff
|
|
20
|
+
- nwn-erf
|
|
20
21
|
- nwn-dsl
|
|
21
22
|
- nwn-irb
|
|
22
23
|
extensions: []
|
|
@@ -39,12 +40,14 @@ files:
|
|
|
39
40
|
- bin/nwn-dsl
|
|
40
41
|
- bin/nwn-gff
|
|
41
42
|
- bin/nwn-irb
|
|
43
|
+
- bin/nwn-erf
|
|
42
44
|
- spec/spec.opts
|
|
43
45
|
- spec/rcov.opts
|
|
44
46
|
- lib/nwn
|
|
45
47
|
- lib/nwn/scripting.rb
|
|
46
48
|
- lib/nwn/yaml.rb
|
|
47
49
|
- lib/nwn/twoda.rb
|
|
50
|
+
- lib/nwn/erf.rb
|
|
48
51
|
- lib/nwn/settings.rb
|
|
49
52
|
- lib/nwn/gff.rb
|
|
50
53
|
- lib/nwn/tlk.rb
|