nwn-lib 0.1 → 0.2
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/CHANGELOG +8 -0
- data/Rakefile +4 -4
- data/bin/nwn-gff-print +5 -36
- data/lib/nwn/gff.rb +54 -0
- data/lib/nwn/twoda.rb +97 -2
- metadata +4 -3
- data/bin/nwn-gff-set +0 -87
data/CHANGELOG
ADDED
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ include FileUtils
|
|
9
9
|
# Configuration
|
10
10
|
##############################################################################
|
11
11
|
NAME = "nwn-lib"
|
12
|
-
VERS = "0.
|
12
|
+
VERS = "0.2"
|
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', \
|
@@ -18,7 +18,7 @@ RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
|
|
18
18
|
Rake::RDocTask.new do |rdoc|
|
19
19
|
rdoc.rdoc_dir = "rdoc"
|
20
20
|
rdoc.options += RDOC_OPTS
|
21
|
-
rdoc.rdoc_files.add ["README", "
|
21
|
+
rdoc.rdoc_files.add ["README", "CHANGELOG", "COPYING", "doc/*.rdoc", "lib/**/*.rb"]
|
22
22
|
end
|
23
23
|
|
24
24
|
desc "Packages up nwn-lib"
|
@@ -30,7 +30,7 @@ spec = Gem::Specification.new do |s|
|
|
30
30
|
s.version = VERS
|
31
31
|
s.platform = Gem::Platform::RUBY
|
32
32
|
s.has_rdoc = true
|
33
|
-
s.extra_rdoc_files = ["README", "COPYING"] + Dir["doc/*.rdoc"]
|
33
|
+
s.extra_rdoc_files = ["README", "CHANGELOG", "COPYING"] + Dir["doc/*.rdoc"]
|
34
34
|
s.rdoc_options += RDOC_OPTS + ["--exclude", "^(examples|extras)\/"]
|
35
35
|
s.summary = "a ruby library for accessing Neverwinter Nights resource files"
|
36
36
|
s.description = s.summary
|
@@ -39,7 +39,7 @@ spec = Gem::Specification.new do |s|
|
|
39
39
|
s.homepage = "http://nwn-lib.elv.es"
|
40
40
|
s.executables = ["nwn-gff-print"]
|
41
41
|
s.required_ruby_version = ">= 1.8.4"
|
42
|
-
s.files = %w(COPYING README Rakefile) + Dir.glob("{bin,doc,spec,lib}/**/*")
|
42
|
+
s.files = %w(COPYING CHANGELOG README Rakefile) + Dir.glob("{bin,doc,spec,lib}/**/*")
|
43
43
|
s.require_path = "lib"
|
44
44
|
s.bindir = "bin"
|
45
45
|
end
|
data/bin/nwn-gff-print
CHANGED
@@ -5,6 +5,7 @@ require 'nwn/gff'
|
|
5
5
|
require 'yaml'
|
6
6
|
|
7
7
|
format = nil
|
8
|
+
types_too = false
|
8
9
|
|
9
10
|
OptionParser.new do |o|
|
10
11
|
o.banner = "Usage: nwn-gff-print [options] file/- [path]"
|
@@ -14,6 +15,9 @@ OptionParser.new do |o|
|
|
14
15
|
o.on "-k", "--kivinen", "Dump as kivinens dump format (like the perl tools)" do
|
15
16
|
format = :kivinen
|
16
17
|
end
|
18
|
+
o.on "-t", "--types", "Dump types as well (only applies to -k, for now)" do
|
19
|
+
types_too = true
|
20
|
+
end
|
17
21
|
end.parse!
|
18
22
|
|
19
23
|
file = ARGV.shift or begin
|
@@ -40,46 +44,11 @@ if path
|
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
43
|
-
def k_format_struct s, prefix = "/", &block
|
44
|
-
if s.is_a?(NWN::Gff::Gff)
|
45
|
-
s = NWN::Gff::Element.new("", :struct, s.root_struct)
|
46
|
-
end
|
47
|
-
if s.is_a?(Array)
|
48
|
-
v = NWN::Gff::Element.new("(unlabeled list)", :list, s)
|
49
|
-
end
|
50
|
-
if s.is_a?(NWN::Gff::Struct)
|
51
|
-
s = NWN::Gff::Element.new("(unlabeled struct)", :struct, s)
|
52
|
-
end
|
53
|
-
case s.type
|
54
|
-
when :struct
|
55
|
-
s.value.each {|k,v|
|
56
|
-
k_format_struct v, prefix + s.label + (s.label == "" ? "" : "/") do |l,v|
|
57
|
-
yield(l, v)
|
58
|
-
end
|
59
|
-
}
|
60
|
-
when :cexolocstr
|
61
|
-
s.value.each {|vv|
|
62
|
-
yield(prefix + s.label + "/" + vv.language.to_s, vv.text)
|
63
|
-
}
|
64
|
-
yield(prefix + s.label + ". ___string_ref", s._str_ref)
|
65
|
-
when :list
|
66
|
-
s.value.each_with_index {|vv, idx|
|
67
|
-
vv.each {|kkk, vvv|
|
68
|
-
k_format_struct vvv, prefix + s.label + "[#{idx}]/" do |l,v|
|
69
|
-
yield(l,v)
|
70
|
-
end
|
71
|
-
}
|
72
|
-
}
|
73
|
-
else
|
74
|
-
yield(prefix + s.label, s.value)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
47
|
case format
|
79
48
|
when :yaml
|
80
49
|
y g
|
81
50
|
when :kivinen
|
82
|
-
|
51
|
+
NWN::Gff.kivinen_format g, "/", types_too do |label, value|
|
83
52
|
puts "%s:\t%s" % [label, value]
|
84
53
|
end
|
85
54
|
else
|
data/lib/nwn/gff.rb
CHANGED
@@ -55,7 +55,61 @@ module NWN
|
|
55
55
|
:float => 'f',
|
56
56
|
:double => 'd',
|
57
57
|
}.freeze
|
58
|
+
|
59
|
+
# Parses +s+ as an arbitary GFF object and yields for each field found,
|
60
|
+
# with the proper prefix.
|
61
|
+
def self.kivinen_format s, prefix = "/", types_too = false, &block
|
62
|
+
if s.is_a?(NWN::Gff::Gff)
|
63
|
+
if types_too
|
64
|
+
yield("/ ____file_type", s.type)
|
65
|
+
yield("/ ____file_version", s.version)
|
66
|
+
end
|
67
|
+
s = NWN::Gff::Element.new("", :struct, s.root_struct)
|
68
|
+
end
|
69
|
+
|
70
|
+
if s.is_a?(Array)
|
71
|
+
v = NWN::Gff::Element.new("(unlabeled list)", :list, s)
|
72
|
+
end
|
73
|
+
|
74
|
+
if s.is_a?(NWN::Gff::Struct)
|
75
|
+
yield(prefix + " ____struct_type", s.struct_id) if types_too
|
76
|
+
s = NWN::Gff::Element.new("(unlabeled struct)", :struct, s)
|
77
|
+
end
|
78
|
+
|
79
|
+
case s.type
|
80
|
+
when :struct
|
81
|
+
yield(prefix + " ____struct_type", s.value.struct_id) if types_too
|
82
|
+
s.value.each {|k,v|
|
83
|
+
kivinen_format v, prefix + s.label + (s.label == "" ? "" : "/"), types_too do |l,v|
|
84
|
+
yield(l, v)
|
85
|
+
end
|
86
|
+
}
|
87
|
+
|
88
|
+
when :cexolocstr
|
89
|
+
|
90
|
+
s.value.each {|vv|
|
91
|
+
yield(prefix + s.label + "/" + vv.language.to_s, vv.text)
|
92
|
+
}
|
93
|
+
yield(prefix + s.label + ". ___string_ref", s._str_ref)
|
94
|
+
|
95
|
+
when :list
|
96
|
+
s.value.each_with_index {|vv, idx|
|
97
|
+
vv.each {|kkk, vvv|
|
98
|
+
kivinen_format vvv, prefix + s.label + "[#{idx}]/", types_too do |l,v|
|
99
|
+
yield(l,v)
|
100
|
+
end
|
101
|
+
}
|
102
|
+
}
|
103
|
+
else
|
104
|
+
yield(prefix + s.label, s.value)
|
105
|
+
end
|
106
|
+
|
107
|
+
if types_too && s.label != ""
|
108
|
+
yield(prefix + s.label + ". ____type", Types.index(s.type).to_s)
|
109
|
+
end
|
110
|
+
end
|
58
111
|
end
|
112
|
+
|
59
113
|
end
|
60
114
|
|
61
115
|
# A GFF object encapsulates a whole GFF identity, with a type,
|
data/lib/nwn/twoda.rb
CHANGED
@@ -1,9 +1,104 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
1
3
|
module NWN
|
2
4
|
module TwoDA
|
3
5
|
class Table
|
4
|
-
end
|
5
6
|
|
6
|
-
|
7
|
+
# An array of all column names present in this 2da table.
|
8
|
+
attr_reader :columns
|
9
|
+
|
10
|
+
# An array of row arrays, without headers.
|
11
|
+
attr_reader :rows
|
12
|
+
|
13
|
+
|
14
|
+
# Creates a new Table object from a given file.
|
15
|
+
#
|
16
|
+
# [+file+] A readable, valid .2da file.
|
17
|
+
def self.new_from_file file
|
18
|
+
self.new IO.read(file)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# Parses a string that represents a valid 2da definition.
|
23
|
+
def initialize bytes
|
24
|
+
magic, empty, header, *data = *bytes.split(/\r?\n/).map {|v| v.strip }
|
25
|
+
|
26
|
+
raise ArgumentError, "Not valid 2da: No valid header found" if
|
27
|
+
magic != "2DA V2.0"
|
28
|
+
|
29
|
+
raise ArgumentError,
|
30
|
+
"Not avalid 2da: Second line should be empty." unless
|
31
|
+
empty == ""
|
32
|
+
|
33
|
+
header = Shellwords.shellwords(header.strip)
|
34
|
+
data.map! {|line|
|
35
|
+
Shellwords.shellwords(line.strip)
|
36
|
+
}
|
37
|
+
|
38
|
+
data.each_with_index {|row, idx|
|
39
|
+
raise ArgumentError, "2da non-continoous: row #{idx} has a non-matching ID #{row[0]}." if idx != row[0].to_i
|
40
|
+
# [1..-1]: Strip off the ID
|
41
|
+
data[idx] = row = row[1..-1]
|
42
|
+
|
43
|
+
raise ArgumentError,
|
44
|
+
"Row #{idx} does not have the appropriate amount of cells (has: #{row.size}, want: #{header.size})." if
|
45
|
+
row.size != header.size
|
46
|
+
}
|
47
|
+
|
48
|
+
@columns = header
|
49
|
+
@rows = data
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Retrieve data by row.
|
54
|
+
#
|
55
|
+
# [+row+] The row to retrieve (starts at 0)
|
56
|
+
# [+column+] The column to retrieve (name or id), or nil for all columns.
|
57
|
+
def by_row row, column = nil
|
58
|
+
column = column_name_to_id column
|
59
|
+
column.nil? ? @rows[row.to_i] : @rows[row.to_i][column]
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# Retrieve data by column.
|
64
|
+
#
|
65
|
+
# [+column+] The column to retrieve (name or id).
|
66
|
+
# [+row+] The row to retrieve (starts at 0), or nil for all rows.
|
67
|
+
def by_col column, row = nil
|
68
|
+
column = column_name_to_id column
|
69
|
+
raise ArgumentError, "column must not be nil." if column.nil?
|
70
|
+
row.nil? ? @rows.map {|v| v[column] } : @rows[row.to_i][column]
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# Translate a column name to its array offset; will validate
|
75
|
+
# and raise an ArgumentError if the given argument is invalid
|
76
|
+
# or the column cannot be resolved.
|
77
|
+
def column_name_to_id column
|
78
|
+
case column
|
79
|
+
when String
|
80
|
+
@columns.index(column) or raise ArgumentError, "Not a valid column name: #{column}"
|
81
|
+
when Fixnum
|
82
|
+
column
|
83
|
+
when NilClass
|
84
|
+
nil
|
85
|
+
else
|
86
|
+
raise ArgumentError, "Invalid column type: #{column} as #{column.class}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns this table as a valid 2da to be written to a file.
|
91
|
+
def to_2da
|
92
|
+
ret = []
|
93
|
+
ret << "2DA V2.0"
|
94
|
+
ret << ""
|
95
|
+
ret << @columns.join("\t")
|
96
|
+
@rows.each_with_index {|row, idx|
|
97
|
+
ret << [idx].concat(row).join("\t")
|
98
|
+
}
|
99
|
+
ret.join("\r\n")
|
100
|
+
end
|
101
|
+
|
7
102
|
end
|
8
103
|
end
|
9
104
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: nwn-lib
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date: 2008-06-
|
6
|
+
version: "0.2"
|
7
|
+
date: 2008-06-29 00:00:00 +02:00
|
8
8
|
summary: a ruby library for accessing Neverwinter Nights resource files
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -30,10 +30,10 @@ authors:
|
|
30
30
|
- Bernhard Stoeckner
|
31
31
|
files:
|
32
32
|
- COPYING
|
33
|
+
- CHANGELOG
|
33
34
|
- README
|
34
35
|
- Rakefile
|
35
36
|
- bin/nwn-gff-print
|
36
|
-
- bin/nwn-gff-set
|
37
37
|
- spec/spec.opts
|
38
38
|
- spec/rcov.opts
|
39
39
|
- lib/nwn
|
@@ -53,6 +53,7 @@ rdoc_options:
|
|
53
53
|
- ^(examples|extras)/
|
54
54
|
extra_rdoc_files:
|
55
55
|
- README
|
56
|
+
- CHANGELOG
|
56
57
|
- COPYING
|
57
58
|
executables:
|
58
59
|
- nwn-gff-print
|
data/bin/nwn-gff-set
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
require 'rubygems'
|
3
|
-
require 'optparse'
|
4
|
-
require 'nwn/gff'
|
5
|
-
require 'yaml'
|
6
|
-
|
7
|
-
format = nil
|
8
|
-
|
9
|
-
OptionParser.new do |o|
|
10
|
-
o.banner = "Usage: nwn-gff-print [options] file/- [path]"
|
11
|
-
o.on "-y", "--yaml", "Dump as yaml" do
|
12
|
-
format = :yaml
|
13
|
-
end
|
14
|
-
o.on "-k", "--kivinen", "Dump as kivinens dump format (like the perl tools)" do
|
15
|
-
format = :kivinen
|
16
|
-
end
|
17
|
-
end.parse!
|
18
|
-
|
19
|
-
file = ARGV.shift or begin
|
20
|
-
$stderr.puts "Required argument: filename to process, or - for stdin (try -h)."
|
21
|
-
exit 1
|
22
|
-
end
|
23
|
-
|
24
|
-
path = ARGV.shift
|
25
|
-
|
26
|
-
if file == "-"
|
27
|
-
bytes = $stdin.read
|
28
|
-
else
|
29
|
-
bytes = IO.read(file)
|
30
|
-
end
|
31
|
-
|
32
|
-
g = NWN::Gff::Reader.read(bytes)
|
33
|
-
|
34
|
-
if path
|
35
|
-
begin
|
36
|
-
g = g[path]
|
37
|
-
rescue Exception => e
|
38
|
-
$stderr.puts "Error: " + e.to_s
|
39
|
-
exit 1
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def k_format_struct s, prefix = "/", &block
|
44
|
-
if s.is_a?(NWN::Gff::Gff)
|
45
|
-
s = NWN::Gff::Element.new("", :struct, s.root_struct)
|
46
|
-
end
|
47
|
-
if s.is_a?(Array)
|
48
|
-
v = NWN::Gff::Element.new("(unlabeled list)", :list, s)
|
49
|
-
end
|
50
|
-
if s.is_a?(NWN::Gff::Struct)
|
51
|
-
s = NWN::Gff::Element.new("(unlabeled struct)", :struct, s)
|
52
|
-
end
|
53
|
-
case s.type
|
54
|
-
when :struct
|
55
|
-
s.value.each {|k,v|
|
56
|
-
k_format_struct v, prefix + s.label + (s.label == "" ? "" : "/") do |l,v|
|
57
|
-
yield(l, v)
|
58
|
-
end
|
59
|
-
}
|
60
|
-
when :cexolocstr
|
61
|
-
s.value.each {|vv|
|
62
|
-
yield(prefix + s.label + "/" + vv.language.to_s, vv.text)
|
63
|
-
}
|
64
|
-
yield(prefix + s.label + ". ___string_ref", s._str_ref)
|
65
|
-
when :list
|
66
|
-
s.value.each_with_index {|vv, idx|
|
67
|
-
vv.each {|kkk, vvv|
|
68
|
-
k_format_struct vvv, prefix + s.label + "[#{idx}]/" do |l,v|
|
69
|
-
yield(l,v)
|
70
|
-
end
|
71
|
-
}
|
72
|
-
}
|
73
|
-
else
|
74
|
-
yield(prefix + s.label, s.value)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
case format
|
79
|
-
when :yaml
|
80
|
-
y g
|
81
|
-
when :kivinen
|
82
|
-
k_format_struct g do |label, value|
|
83
|
-
puts "%s:\t%s" % [label, value]
|
84
|
-
end
|
85
|
-
else
|
86
|
-
puts "Unknown format; try -h"
|
87
|
-
end
|