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/lib/nwn/scripting.rb
CHANGED
data/lib/nwn/settings.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'iconv'
|
2
|
-
|
3
1
|
module NWN
|
4
2
|
SETTING_DEFAULT_VALUES = {
|
5
3
|
'NWN_LIB_IN_ENCODING' => 'ISO-8859-1',
|
@@ -51,20 +49,12 @@ module NWN
|
|
51
49
|
|
52
50
|
# Converts text from native format (such as json) to Gff (required by NWN).
|
53
51
|
def self.iconv_native_to_gff text
|
54
|
-
|
55
|
-
IconvState[:out] != NWN.setting(:out_encoding)
|
56
|
-
IconvState[:in_i] = Iconv.new(NWN.setting(:in_encoding), NWN.setting(:out_encoding))
|
57
|
-
end
|
58
|
-
IconvState[:in_i].iconv(text)
|
52
|
+
text.encode(NWN.setting(:out_encoding))
|
59
53
|
end
|
60
54
|
|
61
55
|
# Converts text from Gff format to native/external, such as json (usually UTF-8).
|
62
56
|
def self.iconv_gff_to_native text
|
63
|
-
|
64
|
-
IconvState[:out] != NWN.setting(:out_encoding)
|
65
|
-
IconvState[:out_i] = Iconv.new(NWN.setting(:out_encoding), NWN.setting(:in_encoding))
|
66
|
-
end
|
67
|
-
IconvState[:out_i].iconv(text)
|
57
|
+
text.encode('UTF-8')
|
68
58
|
end
|
69
59
|
end
|
70
60
|
|
data/lib/nwn/twoda.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'shellwords'
|
2
|
-
|
3
1
|
class Integer
|
4
2
|
# Returns the level that this amount experience resolves to.
|
5
3
|
# Depends on a set-up TwoDA::Cache, and reads from <tt>exptable</tt>.
|
@@ -41,8 +39,17 @@ module NWN
|
|
41
39
|
end
|
42
40
|
|
43
41
|
def method_missing meth, *args
|
44
|
-
|
45
|
-
|
42
|
+
col = meth.to_s
|
43
|
+
assignment = if col =~ /(.+?)=$/
|
44
|
+
col = $1
|
45
|
+
true
|
46
|
+
else
|
47
|
+
false
|
48
|
+
end
|
49
|
+
|
50
|
+
if idx = @table.columns.index(col.downcase) ||
|
51
|
+
idx = @table.columns.index(col)
|
52
|
+
if assignment
|
46
53
|
self[idx] = args.shift or raise ArgumentError,
|
47
54
|
"Need a paramenter for assignments .."
|
48
55
|
else
|
@@ -120,9 +127,9 @@ module NWN
|
|
120
127
|
|
121
128
|
header = data.shift
|
122
129
|
|
123
|
-
header =
|
130
|
+
header = colsplit(header.strip)
|
124
131
|
data.map! {|line|
|
125
|
-
|
132
|
+
colsplit(line.strip)
|
126
133
|
}
|
127
134
|
|
128
135
|
new_row_data = []
|
@@ -277,6 +284,7 @@ module NWN
|
|
277
284
|
row.each_with_index {|cell, column_idx|
|
278
285
|
cell = "****" if cell == ""
|
279
286
|
cell = '"%s"' % cell if cell =~ /\s/
|
287
|
+
cell = cell.to_s
|
280
288
|
rv << cell + " " * (max_cell_size_by_column[column_idx] - cell.size)
|
281
289
|
}
|
282
290
|
ret << rv.join("").rstrip
|
@@ -296,6 +304,35 @@ module NWN
|
|
296
304
|
@newline
|
297
305
|
end)
|
298
306
|
end
|
307
|
+
|
308
|
+
private
|
309
|
+
|
310
|
+
def colsplit(line)
|
311
|
+
line = String.new(line) rescue
|
312
|
+
raise(ArgumentError, "Argument must be a string")
|
313
|
+
line.lstrip!
|
314
|
+
words = []
|
315
|
+
until line.empty?
|
316
|
+
field = ''
|
317
|
+
loop do
|
318
|
+
if line.sub!(/\A"(([^"\\]|\\.)*)"/, '') then
|
319
|
+
snippet = $1.gsub(/\\(.)/, '\1')
|
320
|
+
elsif line =~ /\A"/ then
|
321
|
+
raise ArgumentError, "Unmatched double quote: #{line}"
|
322
|
+
elsif line.sub!(/\A\\(.)?/, '') then
|
323
|
+
snippet = $1 || '\\'
|
324
|
+
elsif line.sub!(/\A([^\s\\"]+)/, '') then
|
325
|
+
snippet = $1
|
326
|
+
else
|
327
|
+
line.lstrip!
|
328
|
+
break
|
329
|
+
end
|
330
|
+
field.concat(snippet)
|
331
|
+
end
|
332
|
+
words.push(field)
|
333
|
+
end
|
334
|
+
words
|
335
|
+
end
|
299
336
|
end
|
300
337
|
|
301
338
|
# An alias for TwoDA::Cache.get
|
@@ -312,7 +349,8 @@ module NWN
|
|
312
349
|
# Call this on application startup.
|
313
350
|
# path spec is a colon-separated list of paths, just like $PATH.
|
314
351
|
def self.setup root_directories
|
315
|
-
@_roots = root_directories.split(
|
352
|
+
@_roots = root_directories.split(File::PATH_SEPARATOR).
|
353
|
+
compact.reject {|x| "" == x.strip }
|
316
354
|
end
|
317
355
|
|
318
356
|
# Get the 2da file with the given name. +name+ is without extension.
|
@@ -327,7 +365,7 @@ module NWN
|
|
327
365
|
|
328
366
|
def self.read_2da name # :nodoc:
|
329
367
|
@_roots.each {|root|
|
330
|
-
file = root +
|
368
|
+
file = root + File::SEPARATOR + name + '.2da'
|
331
369
|
next unless FileTest.exists?(file)
|
332
370
|
return Table.parse(IO.read(file))
|
333
371
|
}
|
data/lib/nwn/version.rb
ADDED
data/lib/nwn/xml_support.rb
CHANGED
@@ -17,7 +17,7 @@ private
|
|
17
17
|
struct.data_version != NWN::Gff::Struct::DEFAULT_DATA_VERSION
|
18
18
|
end
|
19
19
|
|
20
|
-
struct.sort.each {|(
|
20
|
+
struct.sort.each {|(*,v)|
|
21
21
|
s << field_to_xml(v)
|
22
22
|
}
|
23
23
|
s
|
@@ -33,12 +33,12 @@ private
|
|
33
33
|
e['name'] = field.field_label
|
34
34
|
e['type'] = case @format
|
35
35
|
when :modpacker
|
36
|
-
NWN::Gff::Types.
|
36
|
+
NWN::Gff::Types.key(field.field_type).to_s
|
37
37
|
when :nxml
|
38
38
|
field.field_type.to_s
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
case field.field_type
|
42
42
|
when :cexolocstr
|
43
43
|
case @format
|
44
44
|
when :modpacker
|
data/lib/nwn/yaml_support.rb
CHANGED
data/nwn-lib.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/nwn/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Bernhard Stoeckner"]
|
6
|
+
gem.email = ["n@e-ix.net"]
|
7
|
+
gem.description = %q{Neverwinter Nights 1/2 file formats ruby library}
|
8
|
+
gem.summary = gem.description
|
9
|
+
gem.homepage = "https://github.com/niv/nwn-lib"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "nwn-lib"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = NWN::VERSION
|
17
|
+
gem.required_ruby_version = '>= 1.9.1'
|
18
|
+
end
|
data/scripts/reformat_2da
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
#!/usr/bin/env nwn-dsl
|
2
2
|
# vim: ft=ruby
|
3
3
|
|
4
|
-
ARGV.
|
5
|
-
|
6
|
-
t
|
7
|
-
|
8
|
-
|
9
|
-
}
|
4
|
+
if ARGV.size == 0
|
5
|
+
t = TwoDA::Table.parse($stdin.read)
|
6
|
+
$stdout.puts t.to_2da
|
7
|
+
else
|
8
|
+
ARGV.each {|f|
|
9
|
+
log "Working on #{f} .."
|
10
|
+
t = TwoDA::Table.parse(IO.read(f))
|
11
|
+
File.open(f, "wb") {|n| n.puts t.to_2da }
|
12
|
+
log "done."
|
13
|
+
}
|
14
|
+
end
|
data/spec/bin_dsl_spec.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
3
|
describe "nwn-dsl" do
|
4
|
-
|
4
|
+
include BinHelper
|
5
5
|
|
6
6
|
it "runs empty scripts" do
|
7
|
-
t = Tempfile.new(
|
7
|
+
t = Tempfile.new(["nwn-lib", "dsl"])
|
8
8
|
t.close
|
9
9
|
run(t.path)
|
10
10
|
end
|
11
11
|
|
12
12
|
it "runs want/need scripts" do
|
13
|
-
t = Tempfile.new(
|
13
|
+
t = Tempfile.new(["nwn-lib", "dsl"])
|
14
14
|
t.write("need ARGV.shift, :bic")
|
15
15
|
t.close
|
16
16
|
run_bin(t.path, WELLFORMED_GFF_PATH) do |i,o,e|
|
@@ -22,7 +22,7 @@ describe "nwn-dsl" do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it "logs to stderr" do
|
25
|
-
t = Tempfile.new(
|
25
|
+
t = Tempfile.new(["nwn-lib", "dsl"])
|
26
26
|
t.write("log 'hey'")
|
27
27
|
t.close
|
28
28
|
run_bin(t.path, WELLFORMED_GFF_PATH) do |i,o,e|
|
data/spec/bin_erf_spec.rb
CHANGED
@@ -1,38 +1,33 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
3
|
describe "nwn-erf" do
|
4
|
-
|
5
|
-
|
4
|
+
include BinHelper
|
6
5
|
# Create temporary testcase files.
|
7
6
|
before do
|
8
|
-
@
|
7
|
+
@tmpdir = Dir.mktmpdir
|
8
|
+
|
9
|
+
@target = File.join(@tmpdir, "nwn-lib-spec-target.erf")
|
9
10
|
|
10
11
|
@tmp0s = []
|
11
12
|
@tmp1s = []
|
12
13
|
for x in %w{aaa.tga bbbb.erf ccc.bmp 44.txt} do
|
13
|
-
File.open(File.join(@
|
14
|
+
File.open(File.join(@tmpdir, x), "w") do |fn|
|
14
15
|
fn.write(x)
|
15
16
|
end
|
16
|
-
@tmp0s << File.join(@
|
17
|
+
@tmp0s << File.join(@tmpdir, x)
|
17
18
|
end
|
18
19
|
for x in %w{bbbbbbbbbbbbbbbbbbbb.bmp} do
|
19
|
-
File.open(File.join(@
|
20
|
+
File.open(File.join(@tmpdir, x), "w") do |fn|
|
20
21
|
fn.write(x)
|
21
22
|
end
|
22
|
-
@tmp1s << File.join(@
|
23
|
+
@tmp1s << File.join(@tmpdir, x)
|
23
24
|
end
|
24
25
|
@tmp0s.sort!
|
25
26
|
@tmp1s.sort!
|
26
27
|
end
|
27
28
|
|
28
29
|
after do
|
29
|
-
|
30
|
-
File.unlink(f.path) rescue nil
|
31
|
-
}
|
32
|
-
@tmp1s.each {|f|
|
33
|
-
File.unlink(f.path) rescue nil
|
34
|
-
}
|
35
|
-
File.unlink(@target) rescue nil
|
30
|
+
FileUtils.rm_r @tmpdir
|
36
31
|
end
|
37
32
|
|
38
33
|
it "packs -0" do
|
@@ -66,35 +61,35 @@ describe "nwn-erf" do
|
|
66
61
|
it "extracts -0" do
|
67
62
|
run("-c", "-f", @target, *@tmp0s)
|
68
63
|
@tmp0s.each {|f| File.unlink(f) }
|
69
|
-
run("-
|
64
|
+
run("-x", "-f", @target)
|
70
65
|
@tmp0s.each {|f| FileTest.exists?(f).should == true }
|
71
|
-
@tmp0s.each {|f| IO.read(f).should == File.basename(f) }
|
66
|
+
@tmp0s.each {|f| IO.read(f, :encoding => "BINARY").should == File.basename(f) }
|
72
67
|
end
|
73
68
|
|
74
69
|
it "extracts -1" do
|
75
70
|
workon = @tmp0s + @tmp1s
|
76
71
|
run("-1", "-c", "-f", @target, *workon)
|
77
72
|
workon.each {|f| File.unlink(f) }
|
78
|
-
run("-
|
73
|
+
run("-x", "-f", @target)
|
79
74
|
workon.each {|f| FileTest.exists?(f).should == true }
|
80
|
-
workon.each {|f| IO.read(f).should == File.basename(f) }
|
75
|
+
workon.each {|f| IO.read(f, :encoding => "BINARY").should == File.basename(f) }
|
81
76
|
end
|
82
77
|
|
83
78
|
it "creates haks" do
|
84
79
|
run("-H", "-c", "-f", @target, *@tmp0s)
|
85
|
-
IO.read(@target).should =~ /^HAK/
|
80
|
+
IO.read(@target, :encoding => "BINARY").should =~ /^HAK/
|
86
81
|
end
|
87
82
|
|
88
83
|
it "creates mods" do
|
89
84
|
run("-M", "-c", "-f", @target, *@tmp0s)
|
90
|
-
IO.read(@target).should =~ /^MOD/
|
85
|
+
IO.read(@target, :encoding => "BINARY").should =~ /^MOD/
|
91
86
|
end
|
92
87
|
|
93
88
|
it "creates erfs (by default)" do
|
94
89
|
run("-E", "-c", "-f", @target, *@tmp0s)
|
95
|
-
IO.read(@target).should =~ /^ERF/
|
90
|
+
IO.read(@target, :encoding => "BINARY").should =~ /^ERF/
|
96
91
|
run("-c", "-f", @target, *@tmp0s)
|
97
|
-
IO.read(@target).should =~ /^ERF/
|
92
|
+
IO.read(@target, :encoding => "BINARY").should =~ /^ERF/
|
98
93
|
end
|
99
94
|
|
100
95
|
it "adds files from existing archives" do
|
data/spec/bin_gff_spec.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
3
|
describe "nwn-gff" do
|
4
|
-
|
4
|
+
include BinHelper
|
5
|
+
|
6
|
+
before do
|
7
|
+
@tmpdir = Dir.mktmpdir
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
FileUtils.rm_r(@tmpdir)
|
12
|
+
end
|
5
13
|
|
6
14
|
NWN::Gff::InputFormats.each do |in_format, handler|
|
7
15
|
inf = in_format.to_s
|
@@ -11,7 +19,7 @@ describe "nwn-gff" do
|
|
11
19
|
|
12
20
|
it "converts #{inf} to #{otf}" do
|
13
21
|
# prepare the temp file
|
14
|
-
t = Tempfile.new(@
|
22
|
+
t = Tempfile.new('nwn-gff', @tmpdir)
|
15
23
|
t.close
|
16
24
|
|
17
25
|
run("-lg", "-i", WELLFORMED_GFF_PATH, "-k", inf, "-o", t.path)
|
@@ -22,7 +30,7 @@ describe "nwn-gff" do
|
|
22
30
|
end
|
23
31
|
|
24
32
|
it "supports none GNU-style backup" do
|
25
|
-
t = Tempfile.new(@
|
33
|
+
t = Tempfile.new('nwn-gff', @tmpdir)
|
26
34
|
t.close
|
27
35
|
run("-b", "none", "-lg", "-i", WELLFORMED_GFF_PATH, "-kg", "-o", t.path)
|
28
36
|
FileTest.exists?(t.path).should == true
|
@@ -30,7 +38,7 @@ describe "nwn-gff" do
|
|
30
38
|
end
|
31
39
|
|
32
40
|
it "supports numbered GNU-style backup" do
|
33
|
-
t = Tempfile.new(@
|
41
|
+
t = Tempfile.new('nwn-gff', @tmpdir)
|
34
42
|
t.close
|
35
43
|
|
36
44
|
run("-b", "numbered", "-lg", "-i", WELLFORMED_GFF_PATH, "-kg", "-o", t.path)
|
@@ -49,7 +57,7 @@ describe "nwn-gff" do
|
|
49
57
|
end
|
50
58
|
|
51
59
|
it "supports existing with no numbered backups GNU-style backup" do
|
52
|
-
t = Tempfile.new(@
|
60
|
+
t = Tempfile.new('nwn-gff', @tmpdir)
|
53
61
|
t.close
|
54
62
|
|
55
63
|
FileTest.exists?(t.path + "~").should == false
|
@@ -74,7 +82,7 @@ describe "nwn-gff" do
|
|
74
82
|
|
75
83
|
|
76
84
|
it "supports simple GNU-style backup" do
|
77
|
-
t = Tempfile.new(@
|
85
|
+
t = Tempfile.new('nwn-gff', @tmpdir)
|
78
86
|
t.close
|
79
87
|
|
80
88
|
FileTest.exists?(t.path + "~").should == false
|
data/spec/erf_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
|
-
|
3
|
+
shared_examples_for "Erf::Erf" do
|
4
4
|
def wellformed_verify binary, expect_locstr = true
|
5
5
|
t = Erf::Erf.new(StringIO.new binary)
|
6
6
|
|
@@ -40,6 +40,7 @@ describe "Erf::Erf", :shared => true do
|
|
40
40
|
it "reproduces correct ERF binary data" do
|
41
41
|
t = Erf::Erf.new(StringIO.new @erf)
|
42
42
|
io = StringIO.new
|
43
|
+
io.set_encoding 'BINARY'
|
43
44
|
t.write_to(io)
|
44
45
|
io.seek(0)
|
45
46
|
n = io.read
|
data/spec/field_spec.rb
CHANGED
@@ -20,4 +20,13 @@ describe "Gff::Field" do
|
|
20
20
|
NWN.setting(:resref16, nil)
|
21
21
|
end
|
22
22
|
end
|
23
|
+
|
24
|
+
describe ":void" do
|
25
|
+
it "stores data in binary" do
|
26
|
+
gff = Gff::Struct.new do |root|
|
27
|
+
root.add_void 'Test', "\xde\xad\xbe\xef"
|
28
|
+
end.to_gff
|
29
|
+
gff.index("\xde\xad\xbe\xef").should_not be_nil
|
30
|
+
end
|
31
|
+
end
|
23
32
|
end
|
data/spec/gff_spec.rb
CHANGED
@@ -20,8 +20,7 @@ describe "Gff.read/write API" do
|
|
20
20
|
:yaml => %w{yml yaml},
|
21
21
|
:json => %w{json},
|
22
22
|
:nxml => %w{nxml},
|
23
|
-
:kivinen => %w{k kivinen}
|
24
|
-
:marshal => %w{marshal}
|
23
|
+
:kivinen => %w{k kivinen}
|
25
24
|
}.each {|expect, arr|
|
26
25
|
arr.each {|ext|
|
27
26
|
it "guesses the file format #{expect} for extension #{ext} correctly" do
|
data/spec/key_spec.rb
CHANGED