nwn-lib 0.4.4 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -147,3 +147,21 @@ Bernhard Stoeckner (7):
147
147
  bin/nwn-erf: -vt: move column type before filename
148
148
  erf: fix loctable reading breaking on more than one locstr
149
149
  0.4.4-rel
150
+
151
+ === 0.4.5
152
+ Bernhard Stoeckner (14):
153
+ bin/nwn-irb: fix help scriptname
154
+ nwn-dsl: $SCRIPT is the currently-running script
155
+ TwoDA: add .get alias
156
+ Scripting/log: provide #progress to indicate progress within scripts
157
+ guess_file_name: consider non-lowercase extensions
158
+ nwn-gff: $SCRIPT fix
159
+ nwn-irb: include NWN namespace
160
+ Namespace clobbering: Integer provides xp_to_level, level_to_xp
161
+ Gff::Struct: add #to_s
162
+ scripting: satisfy: return object as-is when no conditions are given (fix)
163
+ Scripting: add support to .#save files that were loaded with satisfy/need/want
164
+ Scripting: ask: fix return value of hash and arrays
165
+ TwoDA: add disclaimer for Cache references
166
+ TwoDA: add Table#[], Table#[]=
167
+
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ include FileUtils
9
9
  # Configuration
10
10
  ##############################################################################
11
11
  NAME = "nwn-lib"
12
- VERS = "0.4.4"
12
+ VERS = "0.4.5"
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', \
data/SCRIPTING CHANGED
@@ -34,6 +34,9 @@ way, simply call them with nwn-dsl.
34
34
  DSL stands for domain-specific-language by the way, and this is quite
35
35
  a stretch, considering your scripts will be written in plain old ruby.
36
36
 
37
+ The currently-running script name is in $SCRIPT - you can override this
38
+ to print a custom name in, for example, +log+.
39
+
37
40
  === API
38
41
 
39
42
  There are various helpers available to scripts. See NWN::Gff::Scripting
@@ -13,10 +13,10 @@ end.parse!
13
13
 
14
14
  fail "Not enough arguments (try -h)." unless ARGV.size > 0
15
15
 
16
- $base_script = ARGV.shift
16
+ $SCRIPT = ARGV.shift
17
17
 
18
18
  begin
19
- NWN::Gff::Scripting.run_script(IO.read($base_script), nil, ARGV)
19
+ NWN::Gff::Scripting.run_script(IO.read($SCRIPT), nil, ARGV)
20
20
  rescue => e
21
21
  $stderr.puts e.message
22
22
  if $backtrace
@@ -102,7 +102,7 @@ $options[:informat] or fail "No input format specified."
102
102
  $options[:outformat] or fail "No output format specified."
103
103
 
104
104
  if :auto == $options[:informat]
105
- $options[:informat] = NWN::Gff.guess_file_format($options[:infile])
105
+ $options[:informat] = NWN::Gff.guess_file_format($options[:infile].downcase)
106
106
  fail "Cannot guess infile format from filename, specify with -l." unless
107
107
  $options[:informat]
108
108
  end
@@ -110,7 +110,7 @@ end
110
110
  if $options[:outfile] == "-"
111
111
  $options[:outformat] = $options[:informat] if :in == $options[:outformat]
112
112
  elsif :in == $options[:outformat]
113
- $options[:outformat] = NWN::Gff.guess_file_format($options[:outfile])
113
+ $options[:outformat] = NWN::Gff.guess_file_format($options[:outfile].downcase)
114
114
  fail "Cannot guess outfile format from filename, specify with -k." unless
115
115
  $options[:outformat]
116
116
  end
@@ -138,7 +138,7 @@ $options[:run].each {|file|
138
138
  vputs "Running script file: #{file}"
139
139
  FileTest.exists?(file) or file = file + ".rb"
140
140
  $script = File.expand_path(file)
141
- $base_script = File.basename($script)
141
+ $SCRIPT = File.basename($script)
142
142
  include NWN
143
143
  include NWN::Gff::Scripting
144
144
  NWN::Gff::Scripting.run_script(IO.read(file), data_in)
@@ -6,7 +6,7 @@ require 'irb'
6
6
  require 'irb/completion'
7
7
 
8
8
  OptionParser.new do |o|
9
- o.banner = "Usage: nwn-gff-irb [file]"
9
+ o.banner = "Usage: nwn-irb [file]"
10
10
  end.parse!
11
11
 
12
12
  $file = ARGV.shift
@@ -38,8 +38,7 @@ def read file
38
38
  nil
39
39
  end
40
40
 
41
- include NWN::Gff
42
- include NWN::TwoDA
41
+ include NWN
43
42
 
44
43
  if $file
45
44
  read($file)
@@ -72,7 +72,7 @@ module NWN
72
72
  }
73
73
 
74
74
  def self.guess_file_format(filename)
75
- extension = File.extname(filename)[1..-1]
75
+ extension = File.extname(filename.downcase)[1..-1]
76
76
  FileFormatGuesses[FileFormatGuesses.keys.select {|key| extension =~ key}[0]]
77
77
  end
78
78
 
@@ -82,4 +82,8 @@ module NWN::Gff::Struct
82
82
 
83
83
  super
84
84
  end
85
+
86
+ def to_s
87
+ "<NWN::Gff::Struct #{self.data_type}/#{self.data_version}, #{self.keys.size} fields>"
88
+ end
85
89
  end
@@ -14,6 +14,7 @@ module NWN::Gff::Scripting
14
14
  $code = code
15
15
  $argv = arguments
16
16
  $standalone = run_on.nil?
17
+ $satisfy_loaded = {}
17
18
  run_on ||= Sandbox.new
18
19
 
19
20
  $script_obj_hash = run_on.hash
@@ -27,6 +28,24 @@ module NWN::Gff::Scripting
27
28
  $script_obj_hash != run_on.hash
28
29
  end
29
30
 
31
+ # Save the given object if it was loaded via want/need
32
+ def save object
33
+ fn, hash = $satisfy_loaded[object.object_id]
34
+ if fn
35
+ if hash != object.hash
36
+ File.open(fn, "w") {|f|
37
+ NWN::Gff.write(f, NWN::Gff.guess_file_format(fn), object)
38
+ }
39
+ log "saved #{object.to_s} -> #{fn}"
40
+ else
41
+ log "not saving #{fn}: not modified"
42
+ end
43
+ else
44
+ raise ArgumentError,
45
+ "#save: object #{object.to_s} was not loaded via want/need/satisfy, cannot save"
46
+ end
47
+ end
48
+
30
49
  # This script only runs for the following conditions (see #satisfy).
31
50
  def want *what
32
51
  obj = satisfy(*what)
@@ -47,7 +66,7 @@ module NWN::Gff::Scripting
47
66
  if $standalone
48
67
  log "warn: no need to stop_output on standalone scripts"
49
68
  else
50
- log "#{$base_script}: not emitting any data."
69
+ log "#{$SCRIPT}: not emitting any data."
51
70
  end
52
71
  $stop_output = true
53
72
  end
@@ -94,12 +113,14 @@ module NWN::Gff::Scripting
94
113
  # "object to read from (usually the first script argument)."
95
114
  end
96
115
  obj = NWN::Gff.read(io, NWN::Gff.guess_file_format(fn))
116
+ log "satisfied #{fn} -> #{obj.to_s}"
117
+ $satisfy_loaded[obj.object_id] = [fn, obj.hash]
118
+
119
+ return obj if what.size == 1
97
120
  else
98
121
  obj = self
99
122
  end
100
123
 
101
- return obj if what.size == 1
102
-
103
124
  what.each {|w|
104
125
  case w
105
126
  when Class, Module
@@ -118,15 +139,25 @@ module NWN::Gff::Scripting
118
139
  return nil
119
140
  end
120
141
 
142
+ # You can call this to provide a progress indicator, if your script is long-running.
143
+ # the calculated percentage will be prefixed before each log message.
144
+ #
145
+ # +position+ The number of items in the work queue finished.
146
+ # +total_size+ The total size of the work queue, defaults to ARGV.size.
147
+ def progress position, total_size = nil
148
+ total_size ||= ARGV.size
149
+ $PERCENTAGE_DONE = position.to_f / total_size.to_f * 100
150
+ end
121
151
 
122
152
  # Log a friendly message to stderr.
123
153
  # Use this instead of puts, since SAFE levels greater than 0
124
154
  # will prevent you from doing logging yourself.
125
155
  def log *args
156
+ perc = $PERCENTAGE_DONE.nil? ? "" : " (%d%%)" % [ $PERCENTAGE_DONE.to_i ]
126
157
  if $options
127
- $stderr.puts [$base_script, " on ", $options[:infile], ": ", *args].join("")
158
+ $stderr.puts [$SCRIPT, perc, " on ", $options[:infile], ": ", *args].join("")
128
159
  else
129
- $stderr.puts [$base_script, ": ", *args].join("")
160
+ $stderr.puts [$SCRIPT, perc, ": ", *args].join("")
130
161
  end
131
162
  end
132
163
 
@@ -150,13 +181,17 @@ module NWN::Gff::Scripting
150
181
  ret = nil
151
182
  while true
152
183
  y object
153
- $stderr.print File.basename($base_script) + ": " + question + " "
184
+ $stderr.print File.basename($SCRIPT) + ": " + question + " "
154
185
  ret = $stdin.gets
155
186
  ret = ret.rstrip
156
187
 
157
188
  break if object.nil? || case object
158
189
  when Hash
159
- object.keys.index(ret) || (ret != "" && object.keys.index(ret.to_i))
190
+ if object.keys.index(ret) || (ret != "" && object.keys.index(ret.to_i))
191
+ ret = object[ret] || (ret != "" && object[ret.to_i])
192
+ else
193
+ nil
194
+ end
160
195
  when Regexp
161
196
  ret =~ match
162
197
  when Fixnum
@@ -1,5 +1,19 @@
1
1
  require 'shellwords'
2
2
 
3
+ class Integer
4
+ def xp_to_level
5
+ NWN::TwoDA.get('exptable').rows.each {|row|
6
+ level, exp = row.Level.to_i, row.XP.to_i
7
+ return level - 1 if exp > self
8
+ }
9
+ return nil
10
+ end
11
+
12
+ def level_to_xp
13
+ NWN::TwoDA.get('exptable').by_col("XP", self - 1).to_i
14
+ end
15
+ end
16
+
3
17
  module NWN
4
18
  module TwoDA
5
19
 
@@ -156,6 +170,37 @@ module NWN
156
170
  column = column_name_to_id column
157
171
  column.nil? ? @rows[row.to_i] : (@rows[row.to_i].nil? ? nil : @rows[row.to_i][column])
158
172
  end
173
+ alias_method :[], :by_row
174
+
175
+
176
+ # Set a cell or row value.
177
+ #
178
+ # [+row+] The row to operate on (starts at 0)
179
+ # [+column+] Optional column name or index.
180
+ # [+value+] New value, either a full row, or a single value.
181
+ #
182
+ # Examples:
183
+ # TwoDA.get('portraits')[1, "BaseResRef"] = "hi"
184
+ # TwoDA.get('portraits')[1] = %w{1 2 3 4 5 6}
185
+ def []= row, column = nil, value = nil
186
+ if value.nil?
187
+ value = column
188
+ raise ArgumentError, "Expected array for setting a whole row" unless value.is_a?(Array)
189
+ end
190
+
191
+ if value.is_a?(Array)
192
+ raise ArgumentError, "Given array size does not match table columns (got: #{value.size}, want: #{self.columns.size})" unless value.size == self.columns.size
193
+ new_row = Row.new
194
+ new_row.concat(value.map {|x| x.to_s})
195
+
196
+ @rows[row] = new_row
197
+
198
+ else
199
+ col = column_name_to_id column
200
+ @rows[row][col] = value
201
+
202
+ end
203
+ end
159
204
 
160
205
 
161
206
  # Retrieve data by column.
@@ -237,6 +282,11 @@ module NWN
237
282
  end
238
283
  end
239
284
 
285
+ # An alias for TwoDA::Cache.get
286
+ def self.get name
287
+ NWN::TwoDA::Cache.get(name)
288
+ end
289
+
240
290
  # This is a simple 2da cache.
241
291
  module Cache
242
292
  @_cache = {}
@@ -250,6 +300,8 @@ module NWN
250
300
  end
251
301
 
252
302
  # Get the 2da file with the given name. +name+ is without extension.
303
+ # This being a cache, modifications to the returned Table will be reflected
304
+ # in further calls to Cache.get.
253
305
  def self.get(name)
254
306
  raise Exception,
255
307
  "You need to set up the cache first through the environment variable NWN_LIB_2DA_LOCATION." unless
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
4
+ version: 0.4.5
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-03-09 00:00:00 +01:00
12
+ date: 2009-03-16 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15