nwn-lib 0.4.12 → 0.5.0
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/.gitignore +4 -0
- data/.yardopts +1 -0
- data/{BINARIES → BINARIES.rdoc} +0 -0
- data/{CHEATSHEET → CHEATSHEET.rdoc} +0 -0
- data/Gemfile +9 -0
- data/{HOWTO → HOWTO.rdoc} +0 -0
- data/LICENCE +15 -0
- data/{README → README.rdoc} +9 -15
- data/Rakefile +6 -95
- data/{SCRIPTING → SCRIPTING.rdoc} +0 -0
- data/{SETTINGS → SETTINGS.rdoc} +0 -0
- data/bin/nwn-erf +2 -2
- data/lib/nwn/all.rb +1 -0
- data/lib/nwn/erf.rb +4 -4
- data/lib/nwn/gff.rb +1 -1
- data/lib/nwn/gff/field.rb +16 -6
- data/lib/nwn/gff/reader.rb +8 -4
- data/lib/nwn/gff/struct.rb +6 -4
- data/lib/nwn/gff/writer.rb +2 -2
- data/lib/nwn/key.rb +2 -2
- data/lib/nwn/kivinen_support.rb +3 -1
- data/lib/nwn/res.rb +2 -2
- data/lib/nwn/scripting.rb +1 -1
- data/lib/nwn/settings.rb +2 -12
- data/lib/nwn/twoda.rb +46 -8
- data/lib/nwn/version.rb +3 -0
- data/lib/nwn/xml_support.rb +3 -3
- data/lib/nwn/yaml_support.rb +1 -0
- data/nwn-lib.gemspec +18 -0
- data/scripts/reformat_2da +11 -6
- data/spec/bin_dsl_spec.rb +4 -4
- data/spec/bin_erf_spec.rb +17 -22
- data/spec/bin_gff_spec.rb +14 -6
- data/spec/erf_spec.rb +2 -1
- data/spec/field_spec.rb +9 -0
- data/spec/gff_spec.rb +1 -2
- data/spec/key_spec.rb +1 -1
- data/spec/kivinen_spec.rb +1 -1
- data/spec/rcov.opts +0 -0
- data/spec/spec.opts +0 -0
- data/spec/spec_helper.rb +9 -7
- metadata +106 -102
- data/CHANGELOG +0 -354
- data/COPYING +0 -15
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private lib/**/*.rb - *.rdoc LICENCE
|
data/{BINARIES → BINARIES.rdoc}
RENAMED
File without changes
|
File without changes
|
data/Gemfile
ADDED
data/{HOWTO → HOWTO.rdoc}
RENAMED
File without changes
|
data/LICENCE
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Copyright Bernhard Stoeckner <le@e-ix.net> and contributors. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are
|
4
|
+
permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this list of
|
7
|
+
conditions and the following disclaimer.
|
8
|
+
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list
|
10
|
+
of conditions and the following disclaimer in the documentation and/or other materials
|
11
|
+
provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
14
|
+
INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
15
|
+
FOR A PARTICULAR PURPOSE.
|
data/{README → README.rdoc}
RENAMED
@@ -31,15 +31,15 @@ They should work with NWN2 just as well, since the file format specifications di
|
|
31
31
|
|
32
32
|
==== Also in the box:
|
33
33
|
|
34
|
-
* shell scripts and tools to simplify your life (see BINARIES)
|
34
|
+
* shell scripts and tools to simplify your life (see {file:BINARIES})
|
35
35
|
* extensive developer API
|
36
|
-
* a powerful get-out-of-my-way scripting system for data transformation (see SCRIPTING)
|
36
|
+
* a powerful get-out-of-my-way scripting system for data transformation (see {file:SCRIPTING})
|
37
37
|
|
38
38
|
|
39
39
|
=== Upgrade from 0.3.6 to 0.4.x
|
40
40
|
|
41
41
|
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.
|
42
|
-
I can't help you with your API bindings, but for your YAML dumps, a converter script has been provided (see BINARIES).
|
42
|
+
I can't help you with your API bindings, but for your YAML dumps, a converter script has been provided (see {file:BINARIES}).
|
43
43
|
|
44
44
|
|
45
45
|
=== Attention Unicode/UTF-users
|
@@ -50,25 +50,19 @@ This will be worked around in a future release until the release of ruby 1.9, wh
|
|
50
50
|
|
51
51
|
=== Quickstart
|
52
52
|
|
53
|
-
To use it, simply install the gem
|
53
|
+
To use it, simply install the gem:
|
54
54
|
|
55
|
-
|
55
|
+
gem install nwn-lib
|
56
56
|
|
57
|
-
And do the following in a script of your own devising:
|
57
|
+
And do the following in a script of your own devising (or just use bundler):
|
58
58
|
|
59
59
|
require 'rubygems'
|
60
60
|
require 'nwn/all'
|
61
61
|
|
62
|
-
Also, read BINARIES and HOWTO.
|
62
|
+
Also, read {file:BINARIES} and {file:HOWTO}.
|
63
63
|
|
64
|
-
For nwn-lib scripts, see SCRIPTING.
|
64
|
+
For nwn-lib scripts, see {file:SCRIPTING}.
|
65
65
|
|
66
66
|
For using the developer API, I suggest you start reading NWN::Gff::Struct.
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
The latest source is available through git[http://git.swordcoast.net/?p=nwn/nwn-lib.git;a=summary].
|
71
|
-
|
72
|
-
All stable releases are tagged properly.
|
73
|
-
|
74
|
-
You can reach me via email[mailto:elven@swordcoast.net].
|
68
|
+
The latest source is available through git[https://github.com/niv/nwn-lib].
|
data/Rakefile
CHANGED
@@ -1,97 +1,8 @@
|
|
1
|
-
|
2
|
-
require "
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require "fileutils"
|
6
|
-
include FileUtils
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
require 'yard'
|
7
5
|
|
8
|
-
|
9
|
-
# Configuration
|
10
|
-
##############################################################################
|
11
|
-
NAME = "nwn-lib"
|
12
|
-
VERS = "0.4.12"
|
13
|
-
CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage"]
|
14
|
-
RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
|
15
|
-
'nwn-lib: a ruby library for accessing NWN resource files', \
|
16
|
-
'--main', 'README']
|
6
|
+
YARD::Rake::YardocTask.new
|
17
7
|
|
18
|
-
|
19
|
-
|
20
|
-
Rake::RDocTask.new do |rdoc|
|
21
|
-
rdoc.rdoc_dir = "rdoc"
|
22
|
-
rdoc.options += RDOC_OPTS
|
23
|
-
rdoc.rdoc_files.add DOCS + ["doc/*.rdoc", "lib/**/*.rb"]
|
24
|
-
end
|
25
|
-
|
26
|
-
desc "Packages up nwn-lib"
|
27
|
-
task :package => [:clean]
|
28
|
-
|
29
|
-
spec = Gem::Specification.new do |s|
|
30
|
-
s.name = NAME
|
31
|
-
s.rubyforge_project = 'nwn-lib'
|
32
|
-
s.version = VERS
|
33
|
-
s.platform = Gem::Platform::RUBY
|
34
|
-
s.has_rdoc = true
|
35
|
-
s.extra_rdoc_files = DOCS + Dir["doc/*.rdoc"]
|
36
|
-
s.rdoc_options += RDOC_OPTS + ["--exclude", "^(examples|extras)\/"]
|
37
|
-
s.summary = "a ruby library for accessing Neverwinter Nights resource files"
|
38
|
-
s.description = s.summary
|
39
|
-
s.author = "Bernhard Stoeckner"
|
40
|
-
s.email = "elven@swordcoast.net"
|
41
|
-
s.homepage = "http://nwn-lib.elv.es"
|
42
|
-
s.executables = ["nwn-gff", "nwn-erf", "nwn-dsl", "nwn-irb"]
|
43
|
-
s.required_ruby_version = ">= 1.8.4"
|
44
|
-
s.files = %w(COPYING CHANGELOG README Rakefile) + Dir.glob("{bin,doc,spec,lib,tools,scripts,data}/**/*")
|
45
|
-
s.require_path = "lib"
|
46
|
-
s.bindir = "bin"
|
47
|
-
end
|
48
|
-
|
49
|
-
Rake::GemPackageTask.new(spec) do |p|
|
50
|
-
p.need_tar = true
|
51
|
-
p.gem_spec = spec
|
52
|
-
end
|
53
|
-
|
54
|
-
desc "Install nwn-lib gem"
|
55
|
-
task :install do
|
56
|
-
sh %{rake package}
|
57
|
-
sh %{sudo gem1.8 install pkg/#{NAME}-#{VERS}}
|
58
|
-
end
|
59
|
-
|
60
|
-
desc "Install nwn-lib gem without docs"
|
61
|
-
task :install_no_docs do
|
62
|
-
sh %{rake package}
|
63
|
-
sh %{sudo gem1.8 install pkg/#{NAME}-#{VERS} --no-rdoc --no-ri}
|
64
|
-
end
|
65
|
-
|
66
|
-
desc "Uninstall nwn-lib gem"
|
67
|
-
task :uninstall => [:clean] do
|
68
|
-
sh %{sudo gem1.8 uninstall #{NAME}}
|
69
|
-
end
|
70
|
-
|
71
|
-
require "spec/rake/spectask"
|
72
|
-
|
73
|
-
desc "Run specs with coverage"
|
74
|
-
Spec::Rake::SpecTask.new("spec") do |t|
|
75
|
-
t.spec_files = FileList["spec/*_spec.rb"]
|
76
|
-
t.spec_opts = ["--format s"]
|
77
|
-
t.rcov = true
|
78
|
-
end
|
79
|
-
|
80
|
-
desc "Run specs without coverage"
|
81
|
-
task :default => [:spec_no_cov]
|
82
|
-
Spec::Rake::SpecTask.new("spec_no_cov") do |t|
|
83
|
-
t.spec_files = FileList["spec/*_spec.rb"]
|
84
|
-
t.spec_opts = ["--format s"]
|
85
|
-
end
|
86
|
-
|
87
|
-
desc "Run rcov only"
|
88
|
-
Spec::Rake::SpecTask.new("rcov") do |t|
|
89
|
-
t.spec_files = FileList["spec/*_spec.rb"]
|
90
|
-
t.spec_opts = ["--format s"]
|
91
|
-
t.rcov = true
|
92
|
-
end
|
93
|
-
|
94
|
-
desc "check documentation coverage"
|
95
|
-
task :dcov do
|
96
|
-
sh "find lib -name '*.rb' | xargs dcov"
|
97
|
-
end
|
8
|
+
RSpec::Core::RakeTask.new(:spec)
|
File without changes
|
data/{SETTINGS → SETTINGS.rdoc}
RENAMED
File without changes
|
data/bin/nwn-erf
CHANGED
@@ -164,7 +164,7 @@ case $action
|
|
164
164
|
puts File.basename(a) if $verbose
|
165
165
|
raise ArgumentError, "#{File.basename(a)} already present in erf." if
|
166
166
|
!$allow_duplicates && erf.has?(a)
|
167
|
-
erf.add_file a
|
167
|
+
erf.add_file File.basename(a), File.open(a, "r")
|
168
168
|
}
|
169
169
|
output {|f| erf.write_to(f) }
|
170
170
|
|
@@ -181,7 +181,7 @@ case $action
|
|
181
181
|
when :a
|
182
182
|
raise ArgumentError, "#{File.basename(arg)} already present in erf." if
|
183
183
|
!$allow_duplicates && erf.has?(arg)
|
184
|
-
erf.add_file arg
|
184
|
+
erf.add_file File.basename(arg), File.open(arg, "r")
|
185
185
|
|
186
186
|
when :r
|
187
187
|
erf.content.reject! {|con|
|
data/lib/nwn/all.rb
CHANGED
data/lib/nwn/erf.rb
CHANGED
@@ -133,12 +133,12 @@ module NWN
|
|
133
133
|
[c.resref, @content.index(c), c.res_type, 0].pack("a#{fnlen} V v v")
|
134
134
|
}.join("")
|
135
135
|
|
136
|
-
|
136
|
+
offset = 160 + locstr.size + keylist.size + 8 * @content.size
|
137
137
|
|
138
138
|
reslist = @content.map {|c|
|
139
|
-
|
140
|
-
|
141
|
-
|
139
|
+
r = [offset, c.size].pack("V V")
|
140
|
+
offset += c.size
|
141
|
+
r
|
142
142
|
}.join("")
|
143
143
|
|
144
144
|
offset_to_locstr = 160
|
data/lib/nwn/gff.rb
CHANGED
data/lib/nwn/gff/field.rb
CHANGED
@@ -103,10 +103,11 @@ module NWN::Gff::Field
|
|
103
103
|
return if field_type == :struct
|
104
104
|
|
105
105
|
field_klass_name = field_type.to_s.capitalize
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
|
107
|
+
field_klass = NWN::Gff.const_defined?(field_klass_name, false) ?
|
108
|
+
NWN::Gff.const_get(field_klass_name, false) : nil
|
109
|
+
field_value_klass = NWN::Gff.const_defined?(field_klass_name + 'Value', false) ?
|
110
|
+
NWN::Gff.const_get(field_klass_name + 'Value', false) : nil
|
110
111
|
|
111
112
|
self.extend(field_klass) unless field_klass.nil? ||
|
112
113
|
self.is_a?(field_klass)
|
@@ -227,15 +228,24 @@ module NWN::Gff::Field
|
|
227
228
|
element.extend_meta_classes
|
228
229
|
case element.field_type
|
229
230
|
when :cexolocstr
|
231
|
+
mod = {}
|
230
232
|
element.field_value.each {|x,y|
|
231
|
-
|
233
|
+
mod[x] = NWN.iconv_native_to_gff(y)
|
234
|
+
}
|
235
|
+
mod.each {|x,y|
|
236
|
+
element.field_value.delete(x)
|
237
|
+
element.field_value[x.to_i] = y
|
232
238
|
}
|
233
239
|
when :cexostr
|
234
240
|
element.field_value = NWN.iconv_native_to_gff(element.field_value)
|
235
241
|
|
236
242
|
when :list
|
243
|
+
mod = {}
|
237
244
|
element.field_value.each_with_index {|x,idx|
|
238
|
-
|
245
|
+
mod[idx] = NWN::Gff::Struct.unbox!(x, element)
|
246
|
+
}
|
247
|
+
mod.each {|x,y|
|
248
|
+
element.field_value[x] = y
|
239
249
|
}
|
240
250
|
when :struct
|
241
251
|
element.field_value = NWN::Gff::Struct.unbox!(element.field_value, element)
|
data/lib/nwn/gff/reader.rb
CHANGED
@@ -47,6 +47,7 @@ class NWN::Gff::Reader
|
|
47
47
|
@io.seek(label_offset)
|
48
48
|
@labels = @io.e_read(label_len, "labels")
|
49
49
|
@labels = @labels.unpack("A16" * label_count)
|
50
|
+
@labels.map! {|l| l.encode("ASCII") }
|
50
51
|
|
51
52
|
@io.seek(field_data_offset)
|
52
53
|
@field_data = @io.e_read(field_data_count, "field_data")
|
@@ -74,6 +75,9 @@ class NWN::Gff::Reader
|
|
74
75
|
raise GffError, "struct index #{index} outside of struct_array" if
|
75
76
|
index * 3 + 3 > @structs.size + 1
|
76
77
|
|
78
|
+
file_type = file_type.encode('ASCII') if file_type
|
79
|
+
file_version = file_version.encode('ASCII') if file_version
|
80
|
+
|
77
81
|
struct.struct_id = type
|
78
82
|
struct.data_type = file_type
|
79
83
|
struct.data_version = file_version
|
@@ -155,11 +159,11 @@ class NWN::Gff::Reader
|
|
155
159
|
|
156
160
|
when :cexostr
|
157
161
|
len = @field_data[data_or_offset, 4].unpack("V")[0]
|
158
|
-
@field_data[data_or_offset + 4, len]
|
162
|
+
@field_data[data_or_offset + 4, len].encode(NWN.setting :in_encoding)
|
159
163
|
|
160
164
|
when :resref
|
161
165
|
len = @field_data[data_or_offset, 1].unpack("C")[0]
|
162
|
-
@field_data[data_or_offset + 1, len]
|
166
|
+
@field_data[data_or_offset + 1, len].encode(NWN.setting :in_encoding)
|
163
167
|
|
164
168
|
when :cexolocstr
|
165
169
|
exostr = {}
|
@@ -172,7 +176,7 @@ class NWN::Gff::Reader
|
|
172
176
|
|
173
177
|
str_count.times {
|
174
178
|
id, len = all.unpack("VV")
|
175
|
-
str = all[8, len].unpack("a*")[0]
|
179
|
+
str = all[8, len].unpack("a*")[0].encode(NWN.setting :in_encoding)
|
176
180
|
all = all[(8 + len)..-1]
|
177
181
|
exostr[id] = str
|
178
182
|
}
|
@@ -181,7 +185,7 @@ class NWN::Gff::Reader
|
|
181
185
|
|
182
186
|
when :void
|
183
187
|
len = @field_data[data_or_offset, 4].unpack("V")[0]
|
184
|
-
@field_data[data_or_offset + 4, len].unpack("
|
188
|
+
@field_data[data_or_offset + 4, len].unpack("a*")[0]
|
185
189
|
|
186
190
|
when :struct
|
187
191
|
read_struct data_or_offset, nil, field.parent.data_version
|
data/lib/nwn/gff/struct.rb
CHANGED
@@ -19,7 +19,7 @@ module NWN::Gff::Struct
|
|
19
19
|
attr_reader :element
|
20
20
|
|
21
21
|
def path
|
22
|
-
if @element
|
22
|
+
if defined?(@element) && !@element.nil?
|
23
23
|
@element.path
|
24
24
|
else
|
25
25
|
"/"
|
@@ -41,13 +41,15 @@ module NWN::Gff::Struct
|
|
41
41
|
# Overrides the data type (used by the built-in file format readers).
|
42
42
|
def data_type= k
|
43
43
|
k = nil if k == ""
|
44
|
-
NWN.log_debug("Setting explicit data_type for parented element") if k &&
|
44
|
+
NWN.log_debug("Setting explicit data_type for parented element") if k &&
|
45
|
+
defined?(@element) && !@element.nil?
|
45
46
|
@data_type = k
|
46
47
|
end
|
47
48
|
|
48
49
|
def element= e #:nodoc:
|
49
50
|
@element = e
|
50
|
-
NWN.log_debug("Re-parenting a struct with explicit data_type #{@data_type.inspect}") if e &&
|
51
|
+
NWN.log_debug("Re-parenting a struct with explicit data_type #{@data_type.inspect}") if !e.nil? &&
|
52
|
+
defined?(@data_type) && !@data_type.nil?
|
51
53
|
end
|
52
54
|
|
53
55
|
# Dump this struct as GFF binary data.
|
@@ -106,7 +108,7 @@ module NWN::Gff::Struct
|
|
106
108
|
|
107
109
|
def method_missing meth, *av, &block # :nodoc:
|
108
110
|
if meth.to_s =~ /^add_(.+)$/
|
109
|
-
if NWN::Gff::Types.
|
111
|
+
if NWN::Gff::Types.key($1.to_sym)
|
110
112
|
av.size >= 1 || av.size <= 2 or raise(NoMethodError,
|
111
113
|
"undefined method #{meth} (requires two arguments to infer add_any)")
|
112
114
|
t = $1.to_sym
|
data/lib/nwn/gff/writer.rb
CHANGED
@@ -42,7 +42,7 @@ private
|
|
42
42
|
|
43
43
|
def add_data_field type, label, content
|
44
44
|
label_id = get_label_id_for_label label
|
45
|
-
@fields.push Types.
|
45
|
+
@fields.push Types.key(type), label_id, content
|
46
46
|
(@fields.size - 1) / 3
|
47
47
|
end
|
48
48
|
|
@@ -129,7 +129,7 @@ private
|
|
129
129
|
v.field_value % (2**32)
|
130
130
|
].pack("II")
|
131
131
|
when :void
|
132
|
-
[ v.field_value.size
|
132
|
+
[ v.field_value.size, v.field_value ].pack("Va*")
|
133
133
|
else
|
134
134
|
[v.field_value].pack(format)
|
135
135
|
end
|
data/lib/nwn/key.rb
CHANGED
@@ -87,8 +87,8 @@ module NWN
|
|
87
87
|
size, name_offset, name_size, drives = x.unpack("VVvv")
|
88
88
|
io.seek(name_offset)
|
89
89
|
name = io.e_read(name_size, "name table").unpack("A*")[0]
|
90
|
-
name.gsub!("\\",
|
91
|
-
name = File.expand_path(@root +
|
90
|
+
name.gsub!("\\", File::SEPARATOR)
|
91
|
+
name = File.expand_path(@root + File::SEPARATOR + name)
|
92
92
|
|
93
93
|
_io = File.new(name, "r")
|
94
94
|
@bif << Bif.new(self, _io)
|
data/lib/nwn/kivinen_support.rb
CHANGED
@@ -50,6 +50,8 @@ module NWN::Gff::Handler::Kivinen
|
|
50
50
|
yield(path + "/", path)
|
51
51
|
yield(path + "/ ____struct_type", field.field_value.struct_id)
|
52
52
|
when :cexolocstr
|
53
|
+
when :void
|
54
|
+
yield(path, field.field_value.unpack("H*")[0])
|
53
55
|
else
|
54
56
|
yield(path, field.field_value)
|
55
57
|
end
|
@@ -57,7 +59,7 @@ module NWN::Gff::Handler::Kivinen
|
|
57
59
|
yield(path + ". ____string_ref",field.str_ref) if
|
58
60
|
field.has_str_ref? || field.field_type == :cexolocstr
|
59
61
|
|
60
|
-
yield(path + ". ____type", NWN::Gff::Types.
|
62
|
+
yield(path + ". ____type", NWN::Gff::Types.key(field.field_type)) if
|
61
63
|
types_too
|
62
64
|
|
63
65
|
end
|
data/lib/nwn/res.rb
CHANGED
@@ -55,7 +55,7 @@ module NWN
|
|
55
55
|
|
56
56
|
# Get the extension of this object.
|
57
57
|
def extension
|
58
|
-
NWN::Resources::Extensions.
|
58
|
+
NWN::Resources::Extensions.key(@res_type)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -115,7 +115,7 @@ module NWN
|
|
115
115
|
def initialize path
|
116
116
|
super()
|
117
117
|
@path = path
|
118
|
-
Dir[path + "
|
118
|
+
Dir[path + File::SEPARATOR + "*.*"].each {|x|
|
119
119
|
begin add_file x
|
120
120
|
rescue ArgumentError => e
|
121
121
|
NWN.log_debug e.to_s
|