wolftrans 0.2.0 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c841512ed31767357a132f115dd9c9d5d4d85ae3
4
- data.tar.gz: 13b81d6e79ce6e6e7a3ca202073dd4b8c2a22dd8
3
+ metadata.gz: 04ff8773a7b8a4af514f481410befe41e922aaf2
4
+ data.tar.gz: 80e7cb14b2a9337ef34b687df85cbff1e4cf60a6
5
5
  SHA512:
6
- metadata.gz: 4b63ce1e61df8e456faf61ae7064c8732dfc8626b75262641a9afe76b5f271c5e813daa97042435ea237fedf923e7129b74e363c6fbac6b5322f41a6316a5901
7
- data.tar.gz: faea22c7bbf27d5e4171fa3056306014e869e4c57e4ea9c5697c6359a0a84255ae1b0ccf5ea14ee9d474d2fb00b8f4328790a96e93bbff84443b408d687ea7bc
6
+ metadata.gz: 95a928ce6271aa3bfa37c8f842e92a9fee8c117c06849a52545f49fd2abd33ef64a7277b01342bcd188b1abcb7f36a78213161bd90411c1b42558fab05c0c03a
7
+ data.tar.gz: 7f3ed861199acd6c26fe2ac173892470ab061886b75332fe89d280e59fcf251df47be4a2eab4903670dcc6af2f869249fab874ae416e5981db19a786ca96ba69
data/README.md CHANGED
@@ -36,6 +36,8 @@ Currently, Wolf Trans can be invoked with the command line:
36
36
 
37
37
  If `patch_dir` does not exist, it will be automatically generated with the text contained in the data files of the game in `game_dir`. `out_dir` will contain the patched game.
38
38
 
39
+ **WARNING: OUT_DIR WILL BE *DELETED* IF IT EXISTS. USE CAUTION.**
40
+
39
41
  The behavior of the command line arguments will almost certainly be revised in a future version.
40
42
 
41
43
  ## Todo
@@ -5,6 +5,7 @@ require 'wolftrans'
5
5
 
6
6
  if ARGV.size != 3
7
7
  STDERR.puts "usage: wolftrans game_dir patch_dir out_dir"
8
+ STDERR.puts "WARNING: out_dir will be DELETED. Use caution."
8
9
  exit 1
9
10
  end
10
11
 
@@ -413,6 +413,14 @@ module WolfRpg
413
413
  dump_terminator(coder)
414
414
  end
415
415
 
416
+ def each_filename
417
+ @string_args.each do |str|
418
+ str.scan(/^[^ ]*?[\/\\].*?\.[a-zA-Z0-9]+$/).each do |filename|
419
+ yield filename.gsub('\\', '/')
420
+ end
421
+ end
422
+ end
423
+
416
424
  private
417
425
  def initialize(cid, args, string_args, indent)
418
426
  @cid = cid
@@ -27,6 +27,14 @@ module WolfRpg
27
27
  end
28
28
  end
29
29
 
30
+ def each_filename
31
+ @events.each do |event|
32
+ event.each_filename do |fn|
33
+ yield fn
34
+ end
35
+ end
36
+ end
37
+
30
38
  def grep(needle)
31
39
  end
32
40
 
@@ -149,6 +157,14 @@ module WolfRpg
149
157
  end
150
158
  end
151
159
 
160
+ def each_filename
161
+ @commands.each do |command|
162
+ command.each_filename do |fn|
163
+ yield fn
164
+ end
165
+ end
166
+ end
167
+
152
168
  private
153
169
  MAGIC_NUMBER = [
154
170
  0x0A, 0x00, 0x00, 0x00
@@ -33,36 +33,46 @@ module WolfRpg
33
33
  STDERR.puts "warning: no C1 terminator at the end of '#{dat_filename}'"
34
34
  end
35
35
  end
36
+ end
36
37
 
37
- def dump(project_filename, dat_filename)
38
- FileCoder.open(project_filename, :write) do |coder|
39
- coder.write_int(@types.size)
40
- @types.each do |type|
41
- type.dump_project(coder)
42
- end
38
+ def dump(project_filename, dat_filename)
39
+ FileCoder.open(project_filename, :write) do |coder|
40
+ coder.write_int(@types.size)
41
+ @types.each do |type|
42
+ type.dump_project(coder)
43
43
  end
44
- FileCoder.open(dat_filename, :write, DAT_SEED_INDICES, @crypt_header) do |coder|
45
- if encrypted?
46
- coder.write_byte(@unknown_encrypted_1)
47
- else
48
- coder.write(DAT_MAGIC_NUMBER)
49
- end
50
- coder.write_int(@types.size)
51
- @types.each do |type|
52
- type.dump_dat(coder)
44
+ end
45
+ FileCoder.open(dat_filename, :write, DAT_SEED_INDICES, @crypt_header) do |coder|
46
+ if encrypted?
47
+ coder.write_byte(@unknown_encrypted_1)
48
+ else
49
+ coder.write(DAT_MAGIC_NUMBER)
50
+ end
51
+ coder.write_int(@types.size)
52
+ @types.each do |type|
53
+ type.dump_dat(coder)
54
+ end
55
+ coder.write_byte(0xC1)
56
+ end
57
+ end
58
+
59
+ def each_filename
60
+ @types.each do |type|
61
+ type.data.each do |datum|
62
+ datum.each_filename do |fn|
63
+ yield fn
53
64
  end
54
- coder.write_byte(0xC1)
55
65
  end
56
66
  end
67
+ end
57
68
 
58
- def grep(needle)
59
- @types.each_with_index do |type, type_index|
60
- type.data.each_with_index do |datum, datum_index|
61
- datum.each_translatable do |value, field|
62
- next unless value =~ needle
63
- puts "DB:[#{type_index}]#{type.name}/[#{datum_index}]#{datum.name}/[#{field.index}]#{field.name}"
64
- puts "\t" + value
65
- end
69
+ def grep(needle)
70
+ @types.each_with_index do |type, type_index|
71
+ type.data.each_with_index do |datum, datum_index|
72
+ datum.each_translatable do |value, field|
73
+ next unless value =~ needle
74
+ puts "DB:[#{type_index}]#{type.name}/[#{datum_index}]#{datum.name}/[#{field.index}]#{field.name}"
75
+ puts "\t" + value
66
76
  end
67
77
  end
68
78
  end
@@ -312,6 +322,15 @@ module WolfRpg
312
322
  yield [value, field] unless value.empty? || value.include?("\n")
313
323
  end
314
324
  end
325
+
326
+ def each_filename
327
+ @fields.each do |field|
328
+ next unless field.string?
329
+ self[field].scan(/^[^ ]*?[\/\\].*?\.[a-zA-Z0-9]+$/).each do |filename|
330
+ yield filename.gsub('\\', '/')
331
+ end
332
+ end
333
+ end
315
334
  end
316
335
 
317
336
  DAT_MAGIC_NUMBER = [
@@ -80,6 +80,10 @@ module WolfRpg
80
80
  end
81
81
  end
82
82
 
83
+ def each_filename
84
+ yield @default_pc_graphic.gsub('\\', '/') unless @default_pc_graphic.empty?
85
+ end
86
+
83
87
  private
84
88
  MAGIC_NUMBER = [
85
89
  0x57, 0x00, 0x00, 0x4f, 0x4c, 0x00, 0x46, 0x4d, 0x00
@@ -55,6 +55,14 @@ module WolfRpg
55
55
  end
56
56
  end
57
57
 
58
+ def each_filename
59
+ @events.each do |event|
60
+ event.each_filename do |fn|
61
+ yield fn
62
+ end
63
+ end
64
+ end
65
+
58
66
  #DEBUG method that searches for a string somewhere in the map
59
67
  def grep(needle)
60
68
  @events.each do |event|
@@ -128,6 +136,14 @@ module WolfRpg
128
136
  coder.write_byte(0x70)
129
137
  end
130
138
 
139
+ def each_filename
140
+ @pages.each do |page|
141
+ page.each_filename do |fn|
142
+ yield fn
143
+ end
144
+ end
145
+ end
146
+
131
147
  class Page
132
148
  attr_accessor :id
133
149
  attr_accessor :unknown1
@@ -219,6 +235,15 @@ module WolfRpg
219
235
  coder.write_byte(0x7A)
220
236
  end
221
237
 
238
+ def each_filename
239
+ yield @graphic_name.gsub('\\', '/') unless @graphic_name.empty?
240
+ @commands.each do |command|
241
+ command.each_filename do |fn|
242
+ yield fn
243
+ end
244
+ end
245
+ end
246
+
222
247
  COMMANDS_TERMINATOR = [
223
248
  0x03, 0x00, 0x00, 0x00,
224
249
  ].pack('C*')
@@ -3,6 +3,7 @@ require 'wolfrpg'
3
3
 
4
4
  require 'fileutils'
5
5
  require 'find'
6
+ require 'set'
6
7
 
7
8
  #####################
8
9
  # Loading Game data #
@@ -15,38 +16,29 @@ module WolfTrans
15
16
  end
16
17
  @game_data_dir = Util.join_path_nocase(@game_dir, 'data')
17
18
  if @game_data_dir == nil
18
- raise "could not find data folder in '#{@game_dir}'"
19
+ raise "could not find Data folder in '#{@game_dir}'"
19
20
  end
20
21
 
21
- @maps = {}
22
+ # Load databases, Game.dat, and common events
22
23
  @databases = {}
23
-
24
- # Find and read all necessary data
25
- Dir.entries(@game_data_dir).each do |parent_name|
26
- parent_name_downcase = parent_name.downcase
27
- next unless ['basicdata', 'mapdata'].include? parent_name_downcase
28
- parent_path = "#{@game_data_dir}/#{parent_name}"
29
- Dir.entries(parent_path).each do |basename|
30
- basename_downcase = basename.downcase
31
- extension = File.extname(basename_downcase)
32
- basename_noext = File.basename(basename_downcase, '.*')
33
- filename = "#{parent_path}/#{basename}"
34
- case parent_name_downcase
35
- when 'mapdata'
36
- load_map(filename) if extension == '.mps'
37
- when 'basicdata'
38
- if basename_downcase == 'game.dat'
39
- @game_dat_filename = 'Data/BasicData/Game.dat'
40
- load_game_dat(filename)
41
- elsif extension == '.project'
42
- next if basename_downcase == 'sysdatabasebasic.project'
43
- dat_filename = Util.join_path_nocase(parent_path, "#{basename_noext}.dat")
44
- next if dat_filename == nil
45
- load_game_database(filename, dat_filename)
46
- elsif basename_downcase == 'commonevent.dat'
47
- load_common_events(filename)
48
- end
49
- end
24
+ basicdata_dir = Util.join_path_nocase(@game_data_dir, 'basicdata')
25
+ if basicdata_dir == nil
26
+ raise "could not find BasicData folder in '#{@game_data_dir}'"
27
+ end
28
+ Dir.entries(basicdata_dir).each do |entry|
29
+ entry_downcase = entry.downcase
30
+ filename = "#{basicdata_dir}/#{entry}"
31
+ if entry_downcase == 'game.dat'
32
+ @game_dat_filename = 'Data/BasicData/Game.dat'
33
+ load_game_dat(filename)
34
+ elsif entry_downcase.end_with?('.project')
35
+ next if entry_downcase == 'sysdatabasebasic.project'
36
+ basename = File.basename(entry_downcase, '.*')
37
+ dat_filename = Util.join_path_nocase(basicdata_dir, "#{basename}.dat")
38
+ next if dat_filename == nil
39
+ load_game_database(filename, dat_filename)
40
+ elsif entry_downcase == 'commonevent.dat'
41
+ load_common_events(filename)
50
42
  end
51
43
  end
52
44
 
@@ -60,13 +52,62 @@ module WolfTrans
60
52
  end
61
53
  end
62
54
  end
55
+
56
+ # Gather list of asset and map filenames
57
+ map_names = Set.new
58
+ @assets = {}
59
+ @databases.each_value do |db|
60
+ db.each_filename do |fn|
61
+ fn_downcase = fn.downcase
62
+ @assets[fn_downcase] = fn
63
+ if fn_downcase.end_with?('.mps')
64
+ map_names.add(File.basename(fn_downcase, '.*'))
65
+ end
66
+ end
67
+ end
68
+ @game_dat.each_filename do |fn|
69
+ @assets[fn.downcase] = fn
70
+ end
71
+ @common_events.each_filename do |fn|
72
+ @assets[fn.downcase] = fn
73
+ end
74
+
75
+ # Load maps
76
+ maps_path = Util.join_path_nocase(@game_data_dir, 'mapdata')
77
+ if maps_path == nil
78
+ raise "could not find MapData folder in '#{@game_data_dir}'"
79
+ end
80
+ @maps = {}
81
+ map_names.each do |name|
82
+ map_path = Util.join_path_nocase(maps_path, name + '.mps')
83
+ if map_path == nil
84
+ STDERR.puts "warn: could not find map '#{name}'"
85
+ next
86
+ end
87
+ load_map(map_path)
88
+ end
89
+
90
+ # Gather remaining asset filenames
91
+ @maps.each_value do |map|
92
+ map.each_filename do |fn|
93
+ @assets[fn.downcase] = fn
94
+ end
95
+ end
96
+
97
+ # Make sure not to treat certain kinds of filenames as assets
98
+ @assets.reject! { |k, v| k.start_with?('save/') }
99
+
100
+ # Rewrite asset filenames
101
+ extcounts = Hash.new(0)
102
+ @assets.keys.sort.each do |fn|
103
+ ext = File.extname(fn)[1..-1]
104
+ @assets[fn] = '%04d.%s' % [extcounts[ext], ext]
105
+ extcounts[ext] += 1
106
+ end
63
107
  end
64
108
 
65
109
  # Apply the patch to the files in the game path and write them to the
66
110
  # output directory
67
- DATA_FILE_EXTENSIONS = ['png','jpg','jpeg','bmp','ogg',
68
- 'mp3','wav','mid','midi',
69
- 'dat','project','xxxxx']
70
111
  def apply(out_dir)
71
112
  out_dir = Util.sanitize_path(out_dir)
72
113
  out_data_dir = "#{out_dir}/Data"
@@ -74,21 +115,8 @@ module WolfTrans
74
115
  # Clear out directory
75
116
  FileUtils.rm_rf(out_dir)
76
117
  FileUtils.mkdir_p("#{out_data_dir}/BasicData")
77
- FileUtils.mkdir_p("#{out_data_dir}/MapData")
78
118
 
79
- # Patch all the maps and dump them
80
- @maps.each do |map_name, map|
81
- map.events.each do |event|
82
- next unless event
83
- event.pages.each do |page|
84
- page.commands.each_with_index do |command, cmd_index|
85
- context = Context::MapEvent.from_data(map_name, event, page, cmd_index, command)
86
- patch_command(command, context)
87
- end
88
- end
89
- end
90
- map.dump("#{out_data_dir}/MapData/#{map_name}.mps")
91
- end
119
+ #TODO create directories for each asset
92
120
 
93
121
  # Patch the databases
94
122
  @databases.each do |db_name, db|
@@ -120,26 +148,33 @@ module WolfTrans
120
148
  patch_game_dat
121
149
  @game_dat.dump("#{out_dir}/#{@game_dat_filename}")
122
150
 
123
- # Copy image/sound/music files
124
- Dir.entries(@game_data_dir).each do |entry|
125
- # Skip dot and dot-dot and non-directories
126
- next if entry == '.' || entry == '..'
127
- path = "#{@game_data_dir}/#{entry}"
128
- next unless FileTest.directory? path
129
-
130
- # Find the corresponding folder in the out dir
131
- unless (out_path = Util.join_path_nocase(out_data_dir, entry))
132
- out_path = "#{out_data_dir}/#{entry}"
133
- FileUtils.mkdir_p(out_path)
151
+ # Patch all the maps
152
+ @maps.each do |map_name, map|
153
+ map.events.each do |event|
154
+ next unless event
155
+ event.pages.each do |page|
156
+ page.commands.each_with_index do |command, cmd_index|
157
+ context = Context::MapEvent.from_data(map_name, event, page, cmd_index, command)
158
+ patch_command(command, context)
159
+ end
160
+ end
134
161
  end
162
+ # Translate path
163
+ assetpath = @assets["mapdata/#{map_name.downcase}.mps"]
164
+ fullpath = "#{out_data_dir}/#{assetpath}"
165
+ map.dump(fullpath)
166
+ end
135
167
 
136
- # Find the corresponding folder in the patch
137
- if @patch_data_dir && (asset_entry = Util.join_path_nocase(@patch_data_dir, entry))
138
- copy_data_files("#{@patch_data_dir}/#{asset_entry}", DATA_FILE_EXTENSIONS, out_path)
139
- end
168
+ # Copy remaining BasicData files
169
+ copy_data_files(Util.join_path_nocase(@game_data_dir, 'basicdata'),
170
+ ['xxxxx', 'dat', 'project', 'png'],
171
+ "#{out_data_dir}/BasicData")
140
172
 
141
- # Copy the original game files
142
- copy_data_files(path, DATA_FILE_EXTENSIONS, out_path)
173
+ # Copy remaining assets
174
+ @assets.each_pair do |fn, newfn|
175
+ filename = get_asset_filename(fn)
176
+ next unless filename
177
+ FileUtils.cp(filename, "#{out_data_dir}/#{newfn}")
143
178
  end
144
179
 
145
180
  # Copy fonts
@@ -345,5 +380,24 @@ module WolfTrans
345
380
  FileUtils.cp(path, "#{out_dir}/#{entry}")
346
381
  end
347
382
  end
383
+
384
+ # Get a full filename based on a short asset filename
385
+ def get_asset_filename(fn)
386
+ # Find the correct filename case
387
+ dirname, basename = fn.split('/')
388
+ if @patch_data_dir
389
+ path = Util.join_path_nocase(@patch_data_dir, dirname)
390
+ if path
391
+ path = Util.join_path_nocase(path, basename)
392
+ return path if path
393
+ end
394
+ end
395
+ path = Util.join_path_nocase(@game_data_dir, dirname)
396
+ if path
397
+ path = Util.join_path_nocase(path, basename)
398
+ return path if path
399
+ end
400
+ return nil
401
+ end
348
402
  end
349
403
  end
@@ -1,3 +1,3 @@
1
1
  module WolfTrans
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wolftrans
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mathew Velasquez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-01 00:00:00.000000000 Z
11
+ date: 2017-11-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A utility to translate Wolf RPG Editor games
14
14
  email: mathewvq@gmail.com
@@ -60,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
60
  version: '0'
61
61
  requirements: []
62
62
  rubyforge_project:
63
- rubygems_version: 2.4.5.1
63
+ rubygems_version: 2.6.13
64
64
  signing_key:
65
65
  specification_version: 4
66
66
  summary: A utility to translate Wolf RPG Editor games